使用Minikube集群

目标

  • 了解Kubernetes集群是什么。
  • 了解Minikube是什么。
  • 使用在线终端启动Kubernetes群集。

Kubernetes集群

Kubernetes将底层的计算资源连接在一起对外体现为一个高可用的计算机集群。Kubernetes将资源高度抽象化,允许将容器化的应用程序部署到集群中。为了使用这种新的部署模型,需要将应用程序和使用环境一起打包成容器。与过去的部署模型相比,容器化的应用程序更加灵活和可用,在新的部署模型中,应用程序被直接安装到特定的机器上,Kubernetes能够以更高效的方式在集群中实现容器的分发和调度运行。

Kubernetes集群包括两种类型资源:

集群结构图

Master 负责集群的管理。Master 协调集群中的所有行为/活动,例如应用的运行、修改、更新等。

(Node)节点作为Kubernetes集群中的工作节点,可以是VM虚拟机、物理机。每个node上都有一个Kubelet,用于管理node节点与Kubernetes Master通信。每个Node节点上至少还要运行container runtime(比如docker或者rkt)。

Kubernetes上部署应用程序时,会先通知master启动容器中的应用程序,master调度容器以在集群的节点上运行,node节点使用master公开的Kubernetes API与主节点进行通信。最终用户还可以直接使用Kubernetes API与集群进行交互。

Kubernetes集群可以部署在物理机或虚拟机上。使用Kubernetes开发时,你可以采用Minikube。Minikube可以实现一种轻量级的Kubernetes集群,通过在本地计算机上创建虚拟机并部署只包含单个节点的简单集群。Minikube适用于Linux,MacOS和Windows系统。Minikube CLI提供集群管理的基本操作,包括 start、stop、status、 和delete。

知道Kubernetes是什么了,在线互动教程中:开始使用Minikube来部署集群吧!!

K8S中文社区微信公众号

Kubernetes 基础概述

Kubernetes基础

本互动教程介绍了Kubernetes群集编排系统的基础知识。每个模块都包含Kubernetes的主要功能、概念的一些背景介绍。使用本教程,你可以了解:

  • 在集群上部署容器化应用
  • 集群规模化部署
  • 更新容器化应用的版本
  • 调试容器化应用

这些教程使用Katacoda在浏览器中运行虚拟终端,虚拟终端运行Minikube,它可在任何环境任何地方小规模的部署Kubernetes,且不需要安装任何软件或配置任何东西,每个互动教程都在自己浏览器中运行。

Kubernetes可以做什么?

使用Web服务,用户希望应用程序能够7*24小时全天运行,开发人员希望每天多次部署新的应用版本。通过应用容器化可以实现这些目标,使应用简单、快捷的方式更新和发布,也能实现热更新、迁移等操作。使用Kubernetes能确保程序在任何时间、任何地方运行,还能扩展更多有需求的工具/资源。Kubernetes积累了Google在容器化应用业务方面的经验,以及社区成员的实践,是能在生产环境使用的开源平台。

K8S中文社区微信公众号

Kubernetes的ABAC Mode

基于属性的访问控制(ABAC)

Policy文件格式

使用ABAC模式指定策略文件:--authorization-policy-file=SOME_FILENAME。

文件格式是JSON, one JSON object per line

每一行都是一个“policy 对象”,policy对象具有以下属性:

  • Versioning 属性:
    • apiVersion,字符串类型; 有效值为“abac.authorization.kubernetes.io/v1beta1”。允许版本控制和对策略格式进行转换。
    • kind,字符串类型:有效值为“Policy”。允许版本控制和对策略格式进行转换。
  • spec 属性:
    • Subject-matching 属性:
      • user,字符串类型;
      • group,字符串类型;
    • Resource-matching 属性:
      • apiGroup,字符串类型; 一个API Group。
        • 例如: extensions
        • 通配符:*匹配所有API Group。
      • namespace,字符串类型;一个(namespace)命名空间
        • 例如: kube-system
        • 通配符:*匹配所有资源请求。
      • resource,字符串类型;  资源类型
        • 例如: pods
        • 通配符:*匹配所有资源请求。
    • Non-resource-matching 属性:
      • nonResourcePath,字符串类型; non-resource request paths。
        • 例如:/version 或 /apis
        • 通配符:
          • * 匹配所有non-resource 请求。
          • /foo/* matches all subpaths of /foo/
    • readonly,boolean类型,如果为true,表示该策略仅用于操作get,list和watch。

注意:未设置的属性与设置值为零的属性相同(例如,空字符串,0,false)

Authorization Algorithm

属性设置为"*"将匹配所有属性值。

检查属性的元组以匹配策略文件中的每个策略。如果有一行匹配了请求属性,则请求被授权(但可能会在稍后的认证中失败)。

要允许认证过的用户执行操作,请将Group属性设置"system:authenticated"。

要允许未认证的用户执行操作,请将Group属性设置"system:unauthenticated"。

要允许用户执行任何操作,请编写一个策略,使用apiGroup,namespace,resource和nonResourcePath属性设置为"*"。

例/参考

  1. Alice对所有资源进行操作

    {"apiVersion": "abac.authorization.kubernetes.io/v1beta1", "kind": "Policy", "spec": {"user": "alice", "namespace": "*", "resource": "*", "apiGroup": "*"}}
    
  2. Kubelet可以读取任何pod:
    {"apiVersion": "abac.authorization.kubernetes.io/v1beta1", "kind": "Policy", "spec": {"user": "kubelet", "namespace": "*", "resource": "pods", "readonly": true}}
    
  3. Kubelet可以读/写事件:
    {"apiVersion": "abac.authorization.kubernetes.io/v1beta1", "kind": "Policy", "spec": {"user": "kubelet", "namespace": "*", "resource": "events"}}
    
  4. Bob可以在namespace“projectCaribou”中读取pod:
    {"apiVersion": "abac.authorization.kubernetes.io/v1beta1", "kind": "Policy", "spec": {"user": "bob", "namespace": "projectCaribou", "resource": "pods", "readonly": true}}
    
  5. 谁都可以向所有non-resource paths发出只读请求:
    {"apiVersion": "abac.authorization.kubernetes.io/v1beta1", "kind": "Policy", "spec": {"group": "system:authenticated", "readonly": true, "nonResourcePath": "*"}}
    {"apiVersion": "abac.authorization.kubernetes.io/v1beta1", "kind": "Policy", "spec": {"group": "system:unauthenticated", "readonly": true, "nonResourcePath": "*"}}
    

完整示例文件

A quick note on service accounts

service accounts自动生成user:

system:serviceaccount:<namespace>:<serviceaccountname>

创建新的namespace时也会创建一个新的service account:

system:serviceaccount:<namespace>:default

例如,如果想要在kube-system中对service account默认权限授予API,则需要将此行添加到策略文件中:

{"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"system:serviceaccount:kube-system:default","namespace":"*","resource":"*","apiGroup":"*"}}

最后重启apiserve。

K8S中文社区微信公众号

Kubernetes 管理 Service Accounts

User Accounts 与 Service Accounts

Kubernetes区分普通帐户(user accounts)和服务帐户(service accounts)的原因:

  • 普通帐户是针对(人)用户的,服务账户针对Pod进程。
  • 普通帐户是全局性。在集群所有namespaces中,名称具有惟一性。
  • 通常,群集的普通帐户可以与企业数据库同步,新的普通帐户创建需要特殊权限。服务账户创建目的是更轻量化,允许集群用户为特定任务创建服务账户。
  • 普通帐户和服务账户的审核注意事项不同。
  • 对于复杂系统的配置包,可以包括对该系统的各种组件的服务账户的定义。

Service account automation

三个独立的组件协作,来实现service account的自动化:

  • 一个service account准入控制器(admission controller)
  • 一个 Token controller
  • 一个service account controller

Service Account Admission Controller

通过 Admission Controller插件来实现对pod修改,它是apiserver的一部分。创建或更新pod时会同步进行修改pod。当插件处于激活状态(在大多数发行版中都默认情况)创建或修改pod时,会按以下操作执行:

  1. 如果pod没有设置ServiceAccount,则将ServiceAccount设置为default。
  2. 确保pod引用的ServiceAccount存在,否则将会拒绝请求。
  3. 如果pod不包含任何ImagePullSecrets,则将ServiceAccount的ImagePullSecrets会添加到pod中。
  4. 为包含API访问的Token的pod添加了一个volume。
  5. 把volumeSource添加到安装在pod的每个容器中,挂载在/var/run/secrets/kubernetes.io/serviceaccount。

Token controller

TokenController作为controller-manager的一部分运行。异步行为:

  • 观察serviceAccount的创建,并创建一个相应的Secret 来允许API访问。
  • 观察serviceAccount的删除,并删除所有相应的ServiceAccountToken Secret
  • 观察secret 添加,并确保关联的ServiceAccount存在,并在需要时向secret 中添加一个Token。
  • 观察secret 删除,并在需要时对应 ServiceAccount 的关联

需要使用--service-account-private-key-file 参数选项将Service Account 密匙(key)文件传递给controller-manager中的Token controller。key用于 Service Account Token签名。同样,也需要使用--service-account-key-file 参数选项将相应的(public key)公匙传递给kube-apiserver ,公钥用于在认证期间验证Token。

To create additional API tokens

controller loop能确保每个Service Account都存在一个带有API Token的secret 。如要为Service Account创建额外的API Token,可以使用创建ServiceAccountToken类型的secret,添加与Service Account对应的 annotation 属性,controller会更新令牌:

secret.json:

{
    "kind": "Secret",
    "apiVersion": "v1",
    "metadata": {
        "name": "mysecretname",
        "annotations": {
            "kubernetes.io/service-account.name": "myserviceaccount"
        }
    },
    "type": "kubernetes.io/service-account-token"
}
kubectl create -f ./secret.json
kubectl describe secret mysecretname

要删除/使Service Account token无效

kubectl delete secret mysecretname

Service Account Controller

Service Account Controller在namespaces里管理ServiceAccount,并确保每个有效的namespaces中都存在一个名为“default”的ServiceAccount。

K8S中文社区微信公众号

Kubernetes 授权概述

在Kubernetes中必须经过认证阶段,才到授权请求(授权访问权限)。有关认证的信息,请参阅访问控制概述

确定请求是否通过

Kubernetes使用API​​server授权API请求。它根据策略来评估所有请求属性,是否给于通过。

(Kubernetes使用API​​server,访问控制和依赖特定资源对象的策略由(Admission Controllers)准入控制器处理。)

当配置多个授权模块时,会按顺序检查每个模块,如果有任何模块授权通过,则继续执行下一步的请求。如果所有模块拒绝,则该请求授权失败(返回HTTP 403)。

查看请求属性

Kubernetes只对以下的API请求属性进行检查:

  • user - 认证期间提供的user字符串
  • group - 认证用户所属的组名列表
  • “extra” - 由认证层提供的任意字符串键到字符串值的映射
  • API - 指示请求是否为API resource
  • Request path - 到其他非request端点的路径,如/api或/healthz。
  • API request verb - API verbs get,list,create,update,patch,watch,proxy,redirect,delete,和deletecollection用于请求resource。要确定resource API端点的请求verbs 。
  • HTTP request verb - HTTP verbs get,post,put,和delete用于非资源请求
  • Resource -被访问(仅用于resource 请求)的resource 的ID或名字- *对于使用resource 的请求get,update,patch,和delete,必须提供resource 名称。
  • Subresource - 正在访问的subresource (仅用于请求resource )
  • Namespace - 正在访问对象的命名空间(仅针对命名空间的请求资源)
  • API group - 正在访问的API组(仅用于请求资源)。空字符串指定核心API组

Determine the Request Verb

要确定资源对象API端点请求的动词,请查看HTTP动词以及请求是否对单个资源或资源集合进行操作:

参考下表:

HTTP Verb Request Verb
POST create
GET,HEAD get (for individual resources), list (for collections)
PUT update
PATCH patch
DELETE delete (for individual resources), deletecollection (for collections)

Kubernetes会使用专门的动词检查授权。例如:

授权模块

  • Node - v1.7+支持Node授权,配合NodeRestriction准入控制来限制kubelet仅可访问node、endpoint、pod、service以及secret、configmap、PV和PVC等相关的资源,了解更多Node授权模式的信息,请参阅Node授权
  • ABAC - 基于属性的访问控制(ABAC)定义了访问控制范例,通过将属性组合在一起的策略来授予用户访问权限。ABAC策略可以使用任何类型的属性(用户属性,资源属性,对象,环境属性等)。了解更多ABAC模式的信息,请参阅ABAC模式
  • RBAC - 在Kubernetes1.6版本中新增角色访问控制机制(Role-Based Access,RBAC)让集群管理员可以针对特定使用者或服务账号的角色,进行更精确的资源访问控制。在RBAC中,权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。这就极大地简化了权限的管理。在一个组织中,角色是为了完成各种工作而创造,用户则依据它的责任和资格来被指派相应的角色,用户可以很容易地从一个角色被指派到另一个角色。要了解有关使用RBAC模式的更多信息,请参阅RBAC模式 .. *截至1.6版本 RBAC模式还是beta版本。
  • Webhook - WebHook是一个自定义HTTP回调方法:事件发生时发送HTTP POST; 通过HTTP POST进行简单的事件通知。实现WebHooks的Web应用程序将在某些事件发生时向URL发送消息。了解如何使用Webhook模式的更多信息,请参阅Webhook模式
  • Custom Modules - 可以创建Kubernetes的(Custom Modules)自定义模块。要了解更多信息,请参阅下面的“自定义模块”。

自定义模块

APIserver调用Authorizer接口:

type Authorizer interface {
  Authorize(a Attributes) error
}

来确定是否允许API的操作。

Authorizer插件是实现此接口的模块。Authorizer插件代码在pkg/auth/authorizer/$MODULENAME。

为授权模块使用flags

策略中需要包含一个flag,来指定你的策略包含的哪种授权模块:

使用以下flags:

  • - --authorization-mode=ABAC  基于属性的访问控制(ABAC)模式允许使用本地文件配置策略。
  • - --authorization-mode=RBAC  基于角色的访问控制(RBAC)模式允许使用Kubernetes API创建和存储策略。
  • - --authorization-mode=WebhookWebHook 是一种HTTP回调模式,允许使用远程REST管理授权。
  • - --authorization-mode=AlwaysDeny 此flag 阻止所有请求。仅使用此flag进行测试。
  • - --authorization-mode=AlwaysAllow 此标志允许所有请求。只有在不需要API请求授权的情况下才能使用此标志。

可以选择多个授权模块。如果其中一种模式是AlwaysAllow,则覆盖其他模式,并允许所有的API请求。

版本说明

对于1.2版本,由kube-up.sh配置创建的集群,任何请求都不需要授权。

从1.3版本开始,由kube-up.sh配置创建的集群,默认ABAC授权模块处于启用状态,其输入文件最初设置为允许所有用户执行所有操作。集群管理员需要编辑该文件,或者配置不同的授权器来限制用户可以执行的操作。

下一步

K8S中文社区微信公众号

Kubernetes kubectl 与 Docker 命令关系

在本文中,我们将介绍Kubernetes命令行与docker-cli之间的一些关系。kubectl工具,对于使用过docker-cli 用户来说,kubectl的设计感觉会很熟悉,但是也有一些明显的区别。本文的每个小结都讲解了一个docker子命令,并且列出与kubectl相对应命令。

docker run

如果运行nginx 并且暴露?使用kubectl run

使用docker:

$ docker run -d --restart=always -e DOMAIN=cluster --name nginx-app -p 80:80 nginx
a9ec34d9878748d2f33dc20cb25c714ff21da8d40558b45bfaec9955859075d0
$ docker ps
CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS              PORTS                         NAMES
a9ec34d98787        nginx               "nginx -g 'daemon of   2 seconds ago       Up 2 seconds        0.0.0.0:80->80/tcp, 443/tcp   nginx-app 

使用kubectl:

# start the pod running nginx
$ kubectl run --image=nginx nginx-app --port=80 --env="DOMAIN=cluster"
deployment "nginx-app" created

kubectl run 在Kubernetes集群> = v1.2上将创建名是 “nginx-app”的 Deployment。如果运行的是低的版本,则会创建一个 replication controllers,如果要了解低版本方式,请使用--generator=run/v1,将会创建 replication controllers。查看kubectl run更多详情。现在,我们可以使用上面创建的Deployment来暴露一个新的服务:

# expose a port through with a service
$ kubectl expose deployment nginx-app --port=80 --name=nginx-http
service "nginx-http" exposed

使用kubectl创建一个Deployment,他能保证任何情况下有N个运行nginx 的pods(其中N是默认定义声明的副本数,默认为1个)。它同时会创建一个Services,使用选择器匹配Deployment’s selector。有关详细信息,请参阅快速入门

默认情况下镜像在后台运行,类似于docker run -d ...如果要在前台运行,请使用:

kubectl run [-i] [--tty] --attach <name> --image=<image>

要删除Deployment (及其pod),使用 kubectl delete deployment <name>

docker ps

如何列出当前运行的内容?参考kubectl get

使用docker:

$ docker ps
CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS              PORTS                         NAMES
a9ec34d98787        nginx               "nginx -g 'daemon of   About an hour ago   Up About an hour    0.0.0.0:80->80/tcp, 443/tcp   nginx-app

与kubectl:

$ kubectl get po
NAME              READY     STATUS    RESTARTS   AGE
nginx-app-5jyvm   1/1       Running   0          1h

docker attach

如何连接已经运行在容器中的进程?参考kubectl附件

使用docker:

$ docker ps
CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS              PORTS                         NAMES
a9ec34d98787        nginx               "nginx -g 'daemon of   8 minutes ago       Up 8 minutes        0.0.0.0:80->80/tcp, 443/tcp   nginx-app
$ docker attach a9ec34d98787
...

使用kubectl:

$ kubectl get pods
NAME              READY     STATUS    RESTARTS   AGE
nginx-app-5jyvm   1/1       Running   0          10m
$ kubectl attach -it nginx-app-5jyvm
...

docker exec

如何在容器中执行命令?参考kubectl exec

使用docker:

$ docker ps
CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS              PORTS                         NAMES
a9ec34d98787        nginx               "nginx -g 'daemon of   8 minutes ago       Up 8 minutes        0.0.0.0:80->80/tcp, 443/tcp   nginx-app
$ docker exec a9ec34d98787 cat /etc/hostname
a9ec34d98787

使用kubectl:

$ kubectl get po
NAME              READY     STATUS    RESTARTS   AGE
nginx-app-5jyvm   1/1       Running   0          10m
$ kubectl exec nginx-app-5jyvm -- cat /etc/hostname
nginx-app-5jyvm

交互式命令呢?

使用docker:

$ docker exec -ti a9ec34d98787 /bin/sh
# exit

使用kubectl:

$ kubectl exec -ti nginx-app-5jyvm -- /bin/sh      
# exit

有关更多信息,请参阅获取运行容器中的Shell

docker logs

如何查看进程打印stdout / stderr?参考kubectl logs

使用docker:

$ docker logs -f a9e
192.168.9.1 - - [14/Jul/2015:01:04:02 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.35.0" "-"
192.168.9.1 - - [14/Jul/2015:01:04:03 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.35.0" "-"

使用kubectl:

$ kubectl logs -f nginx-app-zibvs
10.240.63.110 - - [14/Jul/2015:01:09:01 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.26.0" "-"
10.240.63.110 - - [14/Jul/2015:01:09:02 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.26.0" "-"

感觉是时候普及下pods和containers之间的微小差异了; 默认情况下,如果进程退出,pods是不会终止,相反,它会重新启动该进程。这与docker run 配置--restart=always 选项有一个主要区别。要查看以前在Kubernetes中运行的输出,请运行如下:

$ kubectl logs --previous nginx-app-zibvs
10.240.63.110 - - [14/Jul/2015:01:09:01 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.26.0" "-"
10.240.63.110 - - [14/Jul/2015:01:09:02 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.26.0" "-"

有关详细信息,请参阅日志和群集监视

docker stop 和 docker rm

如何停止和删除正在运行的进程?参考kubectl delete

使用docker

$ docker ps
CONTAINER ID        IMAGE               COMMAND                CREATED             STATUS              PORTS                         NAMES
a9ec34d98787        nginx               "nginx -g 'daemon of   22 hours ago        Up 22 hours         0.0.0.0:80->80/tcp, 443/tcp   nginx-app
$ docker stop a9ec34d98787
a9ec34d98787
$ docker rm a9ec34d98787
a9ec34d98787

使用kubectl:

$ kubectl get deployment nginx-app
NAME        DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx-app   1         1         1            1           2m
$ kubectl get po -l run=nginx-app
NAME                         READY     STATUS    RESTARTS   AGE
nginx-app-2883164633-aklf7   1/1       Running   0          2m
$ kubectl delete deployment nginx-app
deployment "nginx-app" deleted
$ kubectl get po -l run=nginx-app
# Return nothing

注意,不要直接删除pod,使用kubectl请删除拥有该pod的Deployment。如果直接删除pod,则Deployment将会重新创建该pod。

docker login

与docker login相比,在kubectl中没有直接相识的命令。如果对于Kubernetes在私有registry中使用感兴趣,请参阅使用私有Registry

docker version

如何获客户端和服务器的版本号?参考kubectl version

使用docker:

$ docker version
Client version: 1.7.0
Client API version: 1.19
Go version (client): go1.4.2
Git commit (client): 0baf609
OS/Arch (client): linux/amd64
Server version: 1.7.0
Server API version: 1.19
Go version (server): go1.4.2
Git commit (server): 0baf609
OS/Arch (server): linux/amd64

使用kubectl:

$ kubectl version
Client Version: version.Info{Major:"0", Minor:"20.1", GitVersion:"v0.20.1", GitCommit:"", GitTreeState:"not a git tree"}
Server Version: version.Info{Major:"0", Minor:"21+", GitVersion:"v0.21.1-411-g32699e873ae1ca-dirty", GitCommit:"32699e873ae1caa01812e41de7eab28df4358ee4", GitTreeState:"dirty"}

docker info

如何获取有关配置和环境信息?参考kubectl cluster-info

使用docker:

$ docker info
Containers: 40
Images: 168
Storage Driver: aufs
 Root Dir: /usr/local/google/docker/aufs
 Backing Filesystem: extfs
 Dirs: 248
 Dirperm1 Supported: false
Execution Driver: native-0.2
Logging Driver: json-file
Kernel Version: 3.13.0-53-generic
Operating System: Ubuntu 14.04.2 LTS
CPUs: 12
Total Memory: 31.32 GiB
Name: k8s-is-fun.mtv.corp.google.com
ID: ADUV:GCYR:B3VJ:HMPO:LNPQ:KD5S:YKFQ:76VN:IANZ:7TFV:ZBF4:BYJO
WARNING: No swap limit support

使用kubectl:

$ kubectl cluster-info
Kubernetes master is running at https://108.59.85.141
KubeDNS is running at https://108.59.85.141/api/v1/namespaces/kube-system/services/kube-dns/proxy
KubeUI is running at https://108.59.85.141/api/v1/namespaces/kube-system/services/kube-ui/proxy
Grafana is running at https://108.59.85.141/api/v1/namespaces/kube-system/services/monitoring-grafana/proxy
Heapster is running at https://108.59.85.141/api/v1/namespaces/kube-system/services/monitoring-heapster/proxy
InfluxDB is running at https://108.59.85.141/api/v1/namespaces/kube-system/services/monitoring-influxdb/proxy
K8S中文社区微信公众号