我命由我,不由天!


  • 搜索
prometheus docker golang linux kubernetes

k8s操作指南

发表于 2020-11-07 | 0 | 阅读次数 1137

查看日志

kubectl logs nginx
kubectl logs nginx --all-containers=true
kubectl logs -lapp=nginx --all-containers=true
kubectl logs -p -c ruby web-1
kubectl logs -f -c ruby web-1
kubectl logs -f -lapp=nginx --all-containers=true # -l后可以空格也可以不空
kubectl logs --tail=20 nginx
kubectl logs --since=1h nginx

调试pod

  • kubectl describe pod myapp-pod # 看pod的启动信息
  • kubectl logs myapp-pod -c pod # 查看pod中指定的container

pod相关命令

  • kubectl delete pod myapp-pod # 删除Pod
  • kubectl get pod -o wide # 查看详细信息
  • kubectl get pods -w # 持续观察
apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
    version: v1
spec:
  containers:
  - name: app
    image: nginx

initContainers demo

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
spec:
  containers:
  - name: myapp-container
    image: busybox
    command: ['sh','-c','echo The app is running! && sleep 3600']
  initContainers:
  - name: init-myservice
    image: busybox
    command: ['sh','-c','until nslookup myservice; do echo waiting for myserivce; sleep 2; done;']
  - name: init-mydb
    image: busybox
    command: ['sh','-c','until nslookup mydb; do echo waiting for mydb; sleep 2; done;']
  • initContainers会在创建container之前执行,并且只有执行成功后才会执行container,而且为顺序执行
  • 此demo为解析myservice和mydb两个service,如果没有就等着延迟两秒
  • 创建两个service
kind: Service
apiVersion: v1
metadata: 
  name: myservice
spec:
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376
- - -
kind: Service
apiVersion: v1
metadata:
  name: mydb
spec:
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9377

原理:

  • 在pod启动过程中,init容器会按顺序在网络和数据卷(pause容器,是一个很小的容器,负责网络和数据集的容器)初始化之后启动,每个容器必须在下一个容器启动之前成功退出
  • 如果由于运行时或退出失败,将导致容器启动失败,它会根据Pod的restartPolicy指定的策略进行重试。然而,如果Pod的restartPolicy设置为Always,Init容器失败时会使用RestartPolicy策略
  • 在所有的Init容器没有成功之前,Pod将不会变成Ready状态。Init容器的端口不会再Service中进行聚集。(容器没成功启动,肯定不能被外界访问)
  • 如果Pod重启,所有的Init容器必须重新执行(init容器必须为幂等状态,每次结果都相同)
  • 对Init容器spec的修改被限制在容器image字段,修改其他字段都不会生效。更改Init容器的image字段,等于重启该Pod
  • Init容器具有应用容器的所有字段。除了readinessProbe,因为init容器无法定义不同于完成的就绪之外的其他状态。这会在验证过程中强制执行(Init只能为完成状态)
  • 在Pod中的每个app和Init容器的名称必须唯一;与任何其他容器共享同一个名称,会在验证时抛出错误(名称必须全局唯一)

容器探针

概念:

探针由kubelet对容器执行的定期诊断。要执行诊断,kubelet调用由容器实现的Handler。有三种类型的处理程序

  • ExecAction: 在容器内执行指定命令。如果命令退出时返回码为0,则诊断成功
  • TCPSocketAction: 对指定端口上的容器的IP地址进行TCP检查。如果端口打开,则诊断被认为成功
  • HTTPGetAction: 对指定的端口和路径上的容器的IP地址执行HTTP GET请求。如果响应的状态码大于等于200且小于400,则诊断成功

诊断结果:

  • 成功
  • 失败
  • 未知

两种探测方式:

  • livenessProbe: 指示容器是否正在运行。如果存活探测失败,则kubelet会杀死容器,并且容器将受到其重启策略的影响。如果容器不提供存活探针,则默认状态为Success
  • readinessProbe:
    指示容器所否准备好服务请求。如果就绪探测失败,端点控制器将从与Pod匹配的所有Service的端点中删除该Pod的Ip地址。初始延迟之前的就绪状态默认为Failture。如果容器不提供就绪探针,则默认状态为Success

就绪监测demo

apiVersion: v1
kind: Pod
metadata:
  name: readiness-httpget-pod
  namespace: default
spec:
  containers:
  - name: readiness-httpget-container
    image: nginx
    imagePullPolicy: IfNotPresent
    readinessProbe:
      httpGet:
        port: 80
        path: /index.html
      initialDelaySeconds: 1
      periodSeconds: 3
  • initialDelaySeconds: 一秒之后监测
  • periodSeconds: 多秒后监测

命令:进入容器

  • kubectl exec podname -c containername -it -- /bin/sh

存活监测

apiVersion: v1
kind: Pod
metadata:
  name: liveness-exec-pod
spec:
  containers:
  - name: liveness-exec-container
    image: nginx
    imagePullPolicy: IfNotPresent
    command: ["/bin/sh","-c","touch /tmp/live; sleep 60; rm -rf /tmp/live; sleep 3600"]
    livenessProbe:
      exec:
        command: ["test","-e","/tmp/live"]
      initialDelaySeconds: 1
      periodSeconds: 3

说明:IfNotPresent策略为本地没有的镜像则去远端拉取,哪怕是latest标签的,也会先从本地先读取,没有再去拉

httpGet

apiVersion: v1
kind: Pod
metadata:
  name: liveness-httpget-pod
spec:
  containers:
  - name: liveness-httpget-container
    image: nginx
    imagePullPolicy: IfNotPresent
    ports:
    - name: http
      containerPort: 80
    livenessProbe:
      httpGet:
        port: http
        path: /index.html
      initialDelaySeconds: 1
      periodSeconds: 3
      timeoutSeconds: 10

tcp

apiVersion: v1
kind: Pod
metadata:
  name: probe-tcp
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
    livenessProbe:
      initialDelaySeconds: 5
      timeoutSeconds: 1
      tcpSocket:
        port: 8080
      periodSeconds: 3

启动退出

apiVersion: v1
kind: Pod
metadata:
  name: lifecycle-demo
spec:
  containers:
  - name: lifecycle-demo-container
    image: nginx
    imagePullPolicy: IfNotPresent
    lifecycle:
      postStart:
        exec:
          command: ["/bin/sh","-c","echo Hello from the postStart Handler > /usr/share/message"]
      preStop:
        exec:
          command: ["/usr/sbin/nginx","-s","quit"]

pod的状态

  • Pending:Pod已被kubernetes接受,但有一个或多个容器尚未被创建,等待时间包括Pod的时间和通过网络下载镜像的时间,这可能需要花点时间
  • Running:该Pod已经绑定到了一个节点上,Pod中所有的容器都已经被创建,至少有一个容器正在运行,或者正处于启动或重启的状态
  • Succeeded:Pod中的所有容器都被成功终止,并且不会再重启
  • Failed:Pod中的所有容器都已终止了,并且至少有一个容器是因为失败终止。也就是说,容器以非0状态退出或者被系统终止
  • Unknown:因为某些原因无法取得Pod的状态,通常是因为与Pod所在主机通信失败

Pod控制器

  • ReplicationController 和 ReplicaSet
  • Deployment
  • DaemonSet
  • StateFulSet
  • Job/CronJob
  • Horizontal Pod Autoscaling

ReplicationController 和 ReplicaSet

  • RC和RS都支持确保容器应用的副本数保持在用户定义的副本数,如果容器异常退出,则自动创建新的pod来替代,多出来的容器自动回收
  • RS支持集合式selector选择(标签)
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: frontend
spec:
  replicas: 3
  selector: 
    matchLabels:
      tier: frontend
  template:
    metadata:
      labels:
        tier: frontend
    spec:
      containers:
      - name: nginx 
        image: nginx
        imagePullPolicy: IfNotPresent
        env:
        - name: GET_HOSTS_FROM
          value: dns
        ports:
        - containerPort: 80
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  selector: 
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80

  • kubectl scale deployment nginx-deployment --replicas=10 # 扩容,但不会改变rs
  • kubectl set image deployment/nginx-deployment nginx=busybox # 更新镜像会新增rs
  • kubectl rollout undo deployment/nginx-deployment [--to-revision=2]# 回滚[到第二个版本]
  • kubectl get pod --show-labels # 查看Pod的标签
  • kubectl label pod podname tier=fronted1 --overwrite=True # 修改pod的标签
  • kubectl rollout status deployments deployment-name # 查看回滚的状态
  • kubectl rollout history deployment/deployment-name # 查看deployment-name的回滚历史记录
  • kubectl rollout pause deployment/deployment-name # 暂停

Deployment

  • 申明式编程 apply
  • 命令式编程 create
  • Deployment为Pod和ReplicaSet提供了一个声明式定义方法,用来替代以前的RC来方便的管理应用
    • 定义Deployment来创建Pod和RS
    • 滚动升级和回滚应用
    • 扩容缩
    • 暂停和继续Deployment

DaemonSet

确保全部Node上运行一个Pod脚本,当有Node加入集群时,也会为他们新增一个Pod。当有Node从集群移除时,这些Pod也会被回收。删除DaemonSet将会删除它创建的所有Pod

  • 运行集群存储daemon
  • 在每个Node上运行日志收集daemon
  • 在每个Node上运行监控daemon
apiVersion: apps/v1
kind: DaemonSet
metadata: 
  name: daemonset-example
  labels: 
    app: daemonset
spec:
  selector:
    matchLabels:
      name: daemonset-example
  template:
    metadata:
      labels:
        name: daemonset-example
    spec:
      containers:
      - name: daemonset-example
        image: nginx

Job

Job负责批处理任务,即仅执行一次的任务,它保证批处理任务的一个或多个Pod成功结束

CronJob

CronJob管理基于时间的Job

  • 在给定时间点只运行一次
  • 周期性运行的Job,例如:数据库备份,发送邮件
    cronjob spec
  • RestartPolicy仅支持Never或OnFaliure
apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: hello
spec:
  schedule: "*/1 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: hello
            image: busybox
            args:
            - /bin/sh
            - -c
            - date; echo Hello from the Kubernetes cluster
          restartPolicy: OnFailure

StatefulSet

statefulset作为Controller为Pod提供唯一的标识。它可以保证部署和scale的顺序
statefulset是为了解决有状态服务的问题

  • 稳定的持久化存储,即Pod重新调度后还是能访问到相同的持久化数据,基于PVC来实现
  • 稳定的网络标识,即Pod重新调度后其PodName和HostName不变,基于Headless Service(即没有Cluster IP的Service)来实现
  • 有序部署,有序扩展,即Pod是有顺序的,在部署或者扩展的时候要依据定义的顺序依次进行(即从0到N-1,在下一个Pod运行之前所有之前的Pod必须都是Running和Ready状态),基于init containers来实现
  • 有序收缩,有序删除(从N-1到0)

HPA 自动扩容

apiVersion

  • kubectl api-versions # 查看apiServer版本
各种apiVersion的含义
alpha

* 该软件可能包含错误。启用一个功能可能会导致bug
* 随时可能会丢弃对该功能的支持,恕不另行通知
 

beta

* 软件经过很好的测试。启用功能被认为是安全的。
* 默认情况下功能是开启的
* 细节可能会改变,但功能在后续版本不会被删除
 

stable

* 该版本名称命名方式:vX这里X是一个整数
* 稳定版本、放心使用
* 将出现在后续发布的软件版本中
 

v1

Kubernetes API的稳定版本,包含很多核心对象:pod、service等
 

apps/v1beta2

在kubernetes1.8版本中,新增加了apps/v1beta2的概念,apps/v1beta1同理
DaemonSet,Deployment,ReplicaSet 和 StatefulSet的当时版本迁入apps/v1beta2,兼容原有的extensions/v1beta1
 

apps/v1

在kubernetes1.9版本中,引入apps/v1,deployment等资源从extensions/v1beta1, apps/v1beta1 和 apps/v1beta2迁入apps/v1,原来的v1beta1等被废弃。
 
apps/v1代表:包含一些通用的应用层的api组合,如:Deployments, RollingUpdates, and ReplicaSets
 

batch/v1

代表job相关的api组合
在kubernetes1.8版本中,新增了batch/v1beta1,后CronJob 已经迁移到了 batch/v1beta1,然后再迁入batch/v1
 

autoscaling/v1

代表自动扩缩容的api组合,kubernetes1.8版本中引入。
这个组合中后续的alpha 和 beta版本将支持基于memory使用量、其他监控指标进行扩缩容
 

extensions/v1beta1

deployment等资源在1.6版本时放在这个版本中,后迁入到apps/v1beta2,再到apps/v1中统一管理
 

certificates.k8s.io/v1beta1

安全认证相关的api组合
 

authentication.k8s.io/v1

资源鉴权相关的api组合

SVC

  • ClusterIp: 默认类型,自动分配一个仅Cluster内部可以访问的虚拟IP
  • NodePort: 在ClusterIP基础上为Service在每台机器上绑定一个端口,这样就可以通过NodePort来访问该服务
  • LoadBalancer: 在NodePort的基础上,借助cloud provider创建一个外部负载均衡器,并将请求转发到NodePort上
  • ExternalName: 把集群外部的服务引入到集群内部中,在集群内部直接使用。没有任何类型代理被创建

实现:
Nginx(172.24.3.123) -> ClusterIP,Port(10.0.0.123:9098) -> WebApp-1 WebApp-2 WebApp-3

  • apiserver 用户通过kubectl命令向apiserver发送创建service命令,apiserver接收到请求后将数据存储到etcd
  • kube-proxy kubernetes的每个节点中都有一个叫做kube-proxy的进程,这个进程负责感知servie,pod的变化,并将变化的信息写入本地的iptables规则中
  • iptables使用NAT等技术将virtualIp的流量转至endpoint中

clusterIP

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deploy
  namespace: default
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
      release: stabel
  template:
    metadata:
      labels:
        app: myapp
        release: stabel
        env: test
    spec:
      containers:
      - name: myapp
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - name: http
          containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: myapp
  namespace: default
spec:
  type: ClusterIP
  selector:
    app: myapp
    release: stabel
  ports:
  - name: http
    port: 80
    targetPort: 80

Headless Service

有时不需要或不想要负载均衡,以及单独的Service IP,遇到这种情况,可以通过指定Cluster IP的值为None,来创建Headless Service,这类Service并不会分配Cluster IP,kube-proxy不会处理它们,而且平台也不会为它们进行负载均衡和路由
kubectl get pods -n kube-system -o wide

dig -t A myapp-headless.default.svc.cluster.local. @10.244.0.2

apiVersion: v1
kind: Service
metadata:
  name: myapp-headless
  namespace: default
spec:
  selector:
    app: myapp
  ClusterIP: "None"
  ports:
  - port: 80
    targetPort: 80

NodePort

apiVersion: v1
kind: Service
metadata:
  name: myapp
  namespace: default
spec:
  type: NodePort
  selector:
    app: myapp
    release: stabel
  ports:
  - name: http
    port: 80
    targetPort: 80

ExternalName

这种类型的Service通过返回CNAME和它的值,可以将服务映射到externalName字段的内容(例如:hub.atguigu.com).ExternalName Service 是Service的特例,没有selector,也没有定义任何的端口和Endpoint.相反,对于运行在集群外部的服务,它通过返回该外部服务的别名这种方式来提供服务

kind: Service
apiVersion: v1
metadata:
  name: my-service-1
  namespace: default
spec:
  type: ExternalName
  externalName: my.database.example.com

指令:

kubectl get pods -n kube-system -o wide

dig -t A my-service-1.default.svc.cluster.local @10.244.0.3

my-service-1.default.svc.cluster.local.	30 IN CNAME my.database.example.com.

Ingress

HTTP代理访问

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-dm
spec:
  replicas: 2
  selector:
    matchLabels:
      name: nginx
  template:
    metadata:
      labels:
        name: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
spec:
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
  selector:
    name: nginx
---
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: nginx-test
spec:
  rules:
    - host: foo.bar.com
      http:
        paths:
        - path: /
          backend:
            serviceName: nginx-svc
            servicePort: 80
  • kubectl get svc -n ingress-nginx # 获取ingress的svc信息
    找到对应端口,然后域名加端口访问

HTTPS代理访问

生成私钥和证书

  • openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=nginxsvc/0=nginxsvc"
    image.png

创建cert存储
kubectl create secret tls tls-secret --key tls.key --cert tls.crt

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: nginx-test
spec:
  tls:
    - hosts:
      - foo.bar.com
      secretName: tls-secret
  rules:
    - host: foo.bar.com
      http:
        paths:
        - path: /
          backend:
            serviceName: nginx-svc
            servicePort: 80

说明:

  • kubectl get deployment # 会有普通的deployment
  • kubectl get svc # 会有普通的svc
  • kubectl get ingress # 会有Ingress
  • kubectl get svc -n ingress-nginx # 会有http和https端口,直接访问域名+端口就ok了

Nginx进行BasicAuth

  • apt install apache2-utils
  • htpasswd -c auth foo
  • kubectl create secret generic basic-auth --from-file=auth
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: ingress-with-auth
  annotations:
    nginx.ingress.kubernetes.io/auth-type: basic
    nginx.ingress.kubernetes.io/auth-secret: basic-auth
    nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required - foo'

spec:
  rules:
  - host: foo.bar.com
    http:
      paths:
      - path: /
        backend:
          serviceName: nginx-svc
          servicePort: 80

image.png

Nginx re

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: nginx-test
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: https://foo.bar.com:31795
spec:
  rules:
  - host: foo10.bar.com
    http:
      paths:
      - path: /
        backend:
          serviceName: nginx-svc
          servicePort: 80

存储

ConfigMap

configMap,许多应用程序会从配置文件、命令行参数或环境变量中读取配置信息。ConfigMap API给我们提供了向容器中注入配置信息的机制,ConfigMap可以用来保存单个属性,也可以用来保存整个配置文件或者json二进制对象

1.使用目录创建

game.properties
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passpharase=UUDDLRLRBABAS

ui.properties
color.good=purple
color.bad=yellow
allow.textmode=true
  • kubectl create configmap game-config --from-file=../dir
  • kubectl describe cm xxx
  • kubectl get cm xxx -o yaml

2.使用单文件创建

同上,把目录换成文件名

3.使用字面值创建

使用文字值创建,利用-from-literal参数传递配置信息

kubectl create configmap special-config --from-literal=special.how=very --from-literal-special.type=charm

代替环境变量

apiVersion: v1
kind: ConfigMap
metadata:
  name: env-config
  namespace: default
data:
  log_level: INFO
---
apiVersion: v1
kind: Pod
metadata:
  name: dapi-test-pod
spec:
  containers:
    - name: test-container
      image: nginx
      imagePullPolicy: IfNotPresent
      command: ["/bin/sh","-c","env"]
      env:
        - name: SPECIAL_LEVEL_KEY
          valueFrom:
            configMapKeyRef:
              name: special-config
              key: special.how
        - name: SPECIAL_TYPE_KEY
          valueFrom:
            configMapKeyRef:
              name: special-config
              key: special.type
      envFrom:
        - configMapRef:
            name: env-config
  restartPolicy: Never

在数据卷里面使用这个ConfigMap,有不同的选项。最基本的就是将文件填入数据卷,在这个文件中,键就是文件名,键值就是文件内容

apiVersion: v1
kind: Pod
metadata:
  name: dapi-test-pod
spec:
  containers:
    - name: test-container
      image: nginx
      imagePullPolicy: IfNotPresent
      command: ["/bin/sh","-c","cat /etc/config/special.how"]
      volumeMounts:
      - name: config-volume
        mountPath: /etc/config
  volumes:
    - name: config-volume
      configMap:
        name: special-config
  restartPolicy: Never

configMap热更新

apiVersion: v1
kind: ConfigMap
metadata:
  name: log-config
data:
  log_level: INFO
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      run: my-nginx
  template:
    metadata:
      labels:
        run: my-nginx
    spec:
      containers:
      - name: my-nginx
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
        volumeMounts:
        - name: config-volume
          mountPath: /etc/config
      volumes:
        - name: config-volume
          configMap:
            name: log-config
  • kubectl edit configmap log-config
    image.png

secret

Opaque类型的数据是一个map类型,要求value是base64编码格式:

echo -n "admin" | base64
echo -n "123456" | base64

secrets.yaml

apiVersion: v1
kind: Secret
metadata:
  name: mysecret
type: Opaque
data:
  password: YWRtaW4=
  username: MTIzNDU2

1.将Secret挂载到Volume中

apiVersion: v1
kind: Pod
metadata:
  labels:
    name: seret-test
  name: seret-test
spec:
  volumes:
  - name: secrets
    secret:
      secretName: mysecret
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: db
    volumeMounts:
    - name: secrets
      mountPath: "/etc/secrets"
      readOnly: true

image.png
2.将Secret导入到环境变量中

apiVersion: apps/v1
kind: Deployment
metadata:
  name: pod-deployment
spec:
  selector:
    matchLabels:
      app: pod-deployment
  replicas: 2
  template:
    metadata:
      labels:
        app: pod-deployment
    spec:
      containers:
      - name: pod-1
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
        env:
        - name: TEST_USER
          valueFrom:
            secretKeyRef:
              name: mysecret
              key: username
        - name: TEST_PASSWORD
          valueFrom:
            secretKeyRef:
              name: mysecret
              key: password

3.使用Kubectl 创建docker registry认证的secret

kubectl create secret docker-registry myregistrykey --docker-server=DOCKER_REGISTRY_SERVER --docker-username=DOCKER_USER --docker-password=DOCKER_PASSWORD --docker-email=DOCKER_EMAIL

在创建Pod的时候,通过imagePullSecrets来引用刚创建的myregistrykey

apiVersion: v1
kind: Pod
metadata:
  name: foo
spec:
  containers:
    - name: foo
      image: nginx
  imagePullSecrets:
    - name: myregistrykey

volume

emptyDir

当Pod被分配给节点时,首先创建emptyDir卷,并且只要该Pod在该节点上运行,该卷就会存在,正如卷的名字所述,它最初是空的。Pod中的容器可以读取和写入emptyDir卷中的相同文件,尽管该卷可以挂载到每个容器中的相同或不同路径上。当出于任何原因从节点中删除Pod时,emptyDir中的数据将被永久删除

apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: nginx
    imagePullPolicy: IfNotPresent
    name: test-container
    volumeMounts:
    - mountPath: /cache
      name: cache-volume
  volumes:
  - name: cache-volume
    emptyDir: {}

hostpath

hostpath卷将主机节点的文件系统中的文件或目录挂载到集群中
用途:

  • 运行需要访问Docker内部的容器,使用/var/lib/docker的hostPath
  • 在容器中运行cAdvisor;使用/dev/cgroups的hostPath

除了所需的path属性之外,用户还可以为hostpath卷指定type

  • 空:空字符串默认用于向后兼容,这意外着在挂载hostPath卷之前不会执行任何检查
  • DirectoryOrCreate:如果给定的路径上没有任何东西存在,那么将根据需要在哪里创建一个空目录,权限设置为0755,与kubelet具有相同的组合所有权
  • Directory: 给定的路径必须存在目录
  • FileOrCreate:如果在给定的路径上没有任何东西存在,那么会根据需要创建一个空文件,权限设置为0644,与kubelet具有相同的组和所有权
  • File:给定的路径下必须存在文件
  • Socket:给定的路径下必须存在UNIX套接字
  • CharDevice:给定的路径下必须存在字符设备
  • BlockDevice: 给定的路径下必须存在块设备
    当Kubernetes按照计划添加资源感知调度时,将无法考虑hostPath使用的资源。在底层主机上创建的文件或目录只能由root写入,您需要在特权容器中以root身份运行进程,或修改主机上的文件权限以便写入hostPath卷
apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: nginx
    name: test-container
    volumeMounts:
    - mountPath: /test-pd
      name: test-volume
  volumes:
  - name: test-volume
    hostPath:
      path: /data
      type: Directory

PV

概念:

PersistenVolume(PV)

是由管理员设置的存储,它是集群的一部分。就像节点是集群中的资源一样,PV也是集群中的资源。PV是Volume之类的卷插件,但具有独立于使用PV的Pod的生命周期。此API对象包含存储实现的细节,即NFS,iSCSI或特定于云供应商的存储系统

PersistemVolumeClaim(PVC)

是用户存储的请求。它与Pod相似。Pod消耗节点资源。PVC消耗PV资源。Pod可以请求特定级别的资源(CPU和内存)。声明可以请求特定的大小和访问模式

静态pv

集群管理员创建一些PV。它们带有可供集群用户使用的实际存储细节。它们存在于Kubernetes Api中,可用于消费

绑定:

master中的控制环路监视新的PVC,寻找匹配的PV,并将它们绑定在一起。如果为新的PVC动态调配PV,则该环路将始终将该PV绑定到PVC,否则,用户总会得到他们所请求的存储,但是容量可能超出要求的数量。一旦PV和PVC绑定后。将是排他性,是一一对应的

PV访问模式

PersistenVoule可以以资源提供者支持的任何方式挂载到主机上,如下表所示,供应商具有不同的功能,每个PV的访问模式都将被设置为该卷支持的特定模式

  • ReadWriteOnce--该卷可以被单个节点以读/写模式挂载RWO
  • ReadOnlyMany--该卷可以被多个节点以只读模式挂载ROM
  • ReadWriteMany--该卷可以被多个节点以读/写模式挂载RWM

回收策略

  • Retain(保留)--手动回收
  • Recycle(回收)--基本擦除(rm -rf /thevolume/*)
  • Delete(删除)--关联的存储资产(例如AWS EBS。。。)

状态

卷可处于一下的某种状态:

  • Available(可用) -- 一块空闲资源还没有被任何声明绑定
  • Bound(已绑定) --卷已经被声明绑定
  • Released(已释放) --声明被删除,但是资源还未被集群重新声明
  • Failed(失败) -- 该卷的自动回收失败

持久化演示说明-NFS

1.安装NFS服务器

yum install -y nfs-common nfs-utils rpcbind
mkdir /nfsdata
chmod 777 /nfsdata
chown nfsnobody /nfsdata
cat /etc/exports/nfsdata *(rw,no_root_squash.no_all_squash,sync)
systemctl start rpcbind
systemctl start nfs

2.部署PV

apiVersion: v1
kind: PersistentVolume
metadata:
  name: nfspv1
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: nfs
  nfs:
    path: /data/nfs
    server: 10.66.66.10

3.创建服务并使用PVC

apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: Statefulset
metadata:
  name: web
spec:
  selector:
    matchLabels:
      app: nginx
  serviceName: "nginx"
  replicas: 3
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumesClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes: ["ReadWriteOnce"]
      storageClassName: "nfs"
      resources:
        requests:
          storage: 1Gi
  • kubectl edit pv xxx 删除ClaimRef手动清除

Scheduler

简介

scheduler 是kubernetes的调度器,主要的任务是把定义的pod分配到集群的节点上

  • 公平:如何保证每个节点都能被分配资源
  • 资源高效利用:集群所有资源最大化使用
  • 效率:调度的性能要好,能够尽快地对大批量的pod完成调度工作
  • 灵活:允许用户根据自己的需求控制调度的逻辑
    Scheduler是作为单独的程序运行的,启动之后会一直坚挺API Server,获取PodSpec.NodeName为空的pod,对每个pod都会创建一个binding,表明该pod应该放到哪个节点上

调度过程

调度分为几个部分:首先是过滤掉不满足条件的节点,这个过程称为predicate;然后对通过的节点按照优先级排序,这个priority;最后从中选择优先级最高的节点。如果中间任何一步骤有错误,就直接返回错误

Predicate有一系列的算法可以使用:

  • PodFitsResources:节点上剩余的资源是否大于pod请求的资源
  • PodFitHost:如果Pod指定了NodeName,检查节点名称是否和NodeName匹配
  • PodFitsHostPorts:节点上已经使用的port是否和pod申请的port冲突
  • PodSelectorMatches:过滤掉和pod指定的label不匹配的节点
  • NoDiskConflict: 已经mount的volume和pod指定的volume不冲突,除非它们都是只读的

如果在predicate过程中没有合适的节点,pod会一直在pending状态,不断重试调度,直到有节点满足条件。经过这个步骤,如果有多个节点满足条件,就继续priorites过程:按照优先级大小对节点排序

优先级由一系列键值对组成,键时该优先级项的名称,值是它的权重。这些优先级选项包括:

  • LeastRequestedPrioity:通过计算CPU和Memory的使用率来决定权重,使用率越低权重越高。换句话说,这个优先级指标倾向于资源使用比例更低的节点
  • BalancedResourceAllocation:节点上CPU和Memory使用率越接近,权重越高。这个应该和上面的一起使用,不应该单独使用
  • ImageLocalityPriority:倾向于已经有要使用镜像的节点,镜像总大小值越大,权重越高

通过算法对所有的优先级项目和权重进行计算,得出最终的结果

节点亲和性

pod.spec.nodeAffinity

  • preferredDuringSchedulingIgnoredDuringExecution:软策略
  • requiredDuringSchedulingIgnoredDuringExecution:硬策略

硬策略

apiVersion: v1
kind: Pod
metadata:
  name: affinity
  labels:
    app: node-affinity-pod
spec:
  containers:
  - name: with-node-affinity
    image: nginx
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoreDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: kubernetes.io/hostname
            operator: NotIn
            values:
            - k8s-node2
  • kubectl get node --show-labels # 查看node的标签

软策略

apiVersion: v1
kind: Pod
metadata:
  name: affinity
  labels:
    app: node-affinity-pod
spec:
  containers:
  - name: with-node-affinity
    image: nginx
  affinity:
    nodeAffinity:
      preferredDuringSchedulingIgnoreDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: source
            operator: In
            values:
            - qikqiak

键值运算关系

  • In: label的值在某个列表中
  • NotIn: label的值不在某个列表中
  • Gt:label的值大于某个值
  • LT:label的值小于某个值
  • Exists:某个label存在
  • DoesNotExist:某个label不存在

Pod亲和性

pod.spec.affinity.podAffinity/podAntiAffinity

  • preferredDuringSchedulingIgnoredDuringExecution: 软策略
  • requiredDuringSchedulingIgnoredDuringExecution:硬策略
apiVersion: v1
kind: Pod
metadata:
  name: pod-3
  labels:
    app: pod-3
spec:
  containers:
  - name: pod-3
    image: nginx
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoreDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: app
            operator: In
            values:
            - pod-1
        topologyKey: kubernetes.io/hostname
    podAntiAffinity:
      preferredDuringSchedulingIgnoreDuringExecution:
      - weight: 1
        podAffinityTerm:
          labelSelector:
            matchExpressions:
            - key: app
              operator: In
              values:
              - pod-2
          topologyKey: kubernetes.io/hostname

亲和性/反亲和性调度策略比较

调度策略

调度策略匹配标签操作符拓扑域支持调度目标
nodeAffinity主机In,NotIn,Exists,DoesNotExist,Gt,Lt否指定主机
podAffinityPODIn,NotIn,Exists,DoesNotExist是POD与指定POD同一拓扑域
podAnitAffinityPODIn,NotIn,Exists,DoesNotExist是POD与指定POD不在同一拓扑域

Taint和Toleration

节点亲和性,是pod的一种属性,它使pod被吸引到一类的节点。Taint则相反,它使节点能够排斥一类特定的pod

Taint和toleration相互配合,可以用来避免pod被分配到不合适的节点上,每个节点都可以应用一个或多个taint,这表示对于那些不能容忍这些taint的pod,是不会被该节点接收的,如果将toleration应用于pod上,则表示这些pod可以被调度到具有匹配taint的节点上

污点(Taint)

1.污点的组成

使用kubectl taint命令可以给某个Node节点设置污点,Node被设置上污点之后就和Pod之间存在了一种相斥的关系,可以让Node拒绝Pod的调度执行,甚至将Node已经存在的Pod驱逐出去

每个污点的组成如下:
key=value:effect

每个污点有一个key和value作为污点的标签,其中value可以为空,effect描述污点的作用。当前taint effect支持如下三个选项

  • NoSchedule:表示k8s不会将Pod调度到具有该污点的Node上
  • PreferNoSchedule:表示k8s将尽量避免将Pod调度到具有该污点的Node上
  • Noexecute:表示k8s将不会将Pod调度到具有该污点的Node上,同时会将Node上已经存在的Pod驱逐出去
  1. 污点的设置,查看和去除
# 设置污点
kubectl taint nodes node1 key1=value:NoSchedule
# 节点说明中,查看Taints字段
kubectl describe pod pod-name
# 去除污点
kubectl taint nodes node1 key1=value:NoSchedule-
容忍

设置了污点的Node将根据taint的effect:NoSchedule PreferNoSchedule NoExecute 和pod之间产生互斥的关系,Pod将在一定程度上不会被调度到Node上。但我们可以再Pod上设置容忍,意思是设置了容忍的Pod将可以容忍污点的存在,可以被调度到存在污点的Node上

pod.spec.tolerations

tolerations:
- key: "key1"
  operator: "Equal"
  value: "value1"
  effect: "NoSchedule"
  tolerationSeconds: 3600
- key: "key1"
  operator: "Equal"
  value: "value1"
  effect: "NoExecute"
- key: "key2"
  operator: "Exists"
  effect: "NoSchedule"
  • 其中key,vaule,effect要与Node上设置的taint保持一致
  • operator的值为Exists将会忽略vaule值
  • tolerationSeconds用于描述当pod需要被驱逐时可以再Pod上继续保持运行的时间
  1. 当不指定key值时,表示容忍所有的污点key:
tolerations:
- operator: "Exists"

2.当不指定effect值时,表示容忍所有污点作用

tolerations:
- key: "key"
  operator: "Exists"

3.有多个Master存在时,防止资源浪费,可以如下设置
kubectl taint nodes Node-name node-role.kubernetes.io/master=:PreferNoSchedule

指定调度节点

1.Pod.spec.nodeName将Pod直接调度到指定的Node节点上,会跳过Scheduler的调度策略,该匹配规则是强制匹配

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myweb
spec:
  replicas: 7
  template:
    metadata:
      labels:
        app: myweb
    spec:
      nodeName: k8s-node01
      containers:
      - name: myweb
        image: nginx
        ports:
        - containerPort: 80

2.Pod.spec.nodeSelector: 通过Kubernetes的label-selector机制选择节点,调度器调度策略匹配label,而后调度Pod到目标节点,该匹配规则属于强制约束

apiVersion: apps/v1
kind: Deployment
metadta:
  name: myweb
spec:
  replicas: 2
  selector:
    labelMatch: 
      app: myweb
  template:
    metadata:
      labels:
        app: myweb
    spec:
      nodeSelector:
        disk: ssd
      containers:
      - name: myweb
        image: nginx
        ports:
        - containerPort: 80
  • kubectl label node k8s-node01 disk=ssd

安全认证

kubernetes作为一个分布式集群的管理工具,保证集群的安全性是其一个重要的任务。API Sever是集群内部各个组件通信的中介,也是外部控制的入口。所以Kubernetes的安全机制基本就是围绕保护API Sever来设计的。Kubernetes使用了认证、鉴权,准入控制三步来保证API Server的安全

认证

  • HTTP Token认证:通过一个Token来识别合法用户
    • HTTP Token的认证是用一个很长的特殊编码方式的并且被难以模仿的字符串-Token来表达客户的一种方式。Token是一个很长的很复杂的字符串,每一个Token对应一个用户名存储在API Server能访问的文件中。当客户端发起API调用请求时,需要在HTTP Header里放入Token
  • HTTP Base认证:通过用户名+密码的方式认证
    • 用户名+:+密码用BASE64算法进行编码后的字符串放在HTTP Request中的Headther Authorization域里发送给服务端,服务端收到后进行编码,获取用户名和密码
  • 最严格的HTTPS证书认证:基于CA根证书签名的客户端身份认证方式
    image.png

需要访问API Sever的组件

  • Kubernetes组件对API Server的访问: kubectl,Controller Manager,Scheduler,kubelet,kube-proxy
  • Kubernetes管理的Pod对容器的访问:Pod(dashborad也是以Pod形式运行)

安全性说明:

  • Controller Manager, Scheduler 与 API Server在同一台机器,所以直接使用API Server的非安全端口访问, --insecure-bind-address=127.0.0.1
  • kubectl,kubelet,kube-proxy访问API Server就都需要证书进行HTTPS双向认证

证书颁发:

  • 手动签发:通过k8s集群的根ca进行签发HTTPS证书
  • 自动签发:kubelet首次访问API Server时,使用token做认证,通过后,Controller Manager会为kubelet生成一个证书,以后的访问都是用证书做认证

kubeconfig

  • kubeconfig文件包含集群参数(CA证书、API Server地址),客户端参数(上面生成的证书和私钥),集群context信息(集群名称,用户名)。Kubenetes组件通过启动时指定不同的kubeconfig文件可以切换到不同的集群
  • ~/.kube/config 就是config文件

ServiceAccount

  • Pod中的容器访问API Server。因为Pod的创建、销毁是动态的,所以要为它手动生成证书就不可行了。kubenetes使用了Service Account解决Pod访问API Server的认证问题

Secret与SA的关系

  • Kubernetes设计了一种资源对象叫做Secret,分为两类,一种是用于ServiceAccount的service-account-token,另一种是用于保存用户自定义保密信息的Opaque。ServiceAccount中用到包含三个部分:Token、ca.crt、namespace
    • token是使用API Server私钥签名的JWT。用于访问API Server时,Server端认证
    • ca.crt,根证书。用于Client端验证API Server发送的证书
    • namespace,标识这个service-account-token的作用域名空间

总结:

image.png

鉴权

  • AlwaysDeny: 拒绝所有的请求
  • AlwaysAllow: 允许接收所有请求
  • ABAC: 基于属性的访问控制,标识使用用户配置的授权规则对用户进行匹配和控制
  • Webbook:通过调用外部REST服务对用户进行授权
  • RBAC:基于角色的访问控制

RBAC

  • 对集群中的资源和非资源均拥有完整的覆盖
  • 整个RBAC完全由几个API对象完成
  • 可以再运行时进行调整,无需重启API Server

1.RBAC的API资源对象说明

RBAC引入4个新的顶级资源对象:Role、ClusterRole、RoleBinding、ClusterRoleBinding,4种对象类型均可以通过kubectl与API操作

需要注意的是kubenetes并不会提供用户管理,由CA申请证书时,提供

{
    "CN": "admin",
    "host": [],
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
            "C": "CN",
            "ST": "HangZhou",
            "L": "XS",
            "O": "system:masters",
            "OU": "System"
        }
    ]
}
# 其中CN为User, names.o为Group

Role and ClusterRole

在RBAC API中,Role表示一组规则权限,权限只会增加,不存在一个资源一开始就有很多权限而通过RBAC对其进行减少的操作,Role可以定义一个namespace中,如果想要跨namespace则可以创建ClusterRole

kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  namespace: default
  name: pod-reader
rules:
- apiGroups: [""] # "" indicates the core API group
  resources: ["pods"]
  verbs: ["get", "watch", "list"]

ClusterRole具有与Role相同的权限角色控制能力,不同的是ClusterRole是集群级别的,ClusterRole可以用于:

  • 集群级别的资源控制
  • 非资源型endpoints
  • 所有命名空间资源控制
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: secret-reader
rules:
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["get","watch","list"]

RoleBinding and ClusterRoleBinding

RoleBinding 可以将角色中定义的权限授予用户或用户组,RoleBinding包含一组权限列表,权限列表中包含有不同形式的待授权资源类型;RoleBinding同样包含对被Bind的Role引用;RoleBinding适用于某个命名空间内授权,而ClusterRoleBinding适用于集群范围内的授权

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: read-pods
  namespace: default
subjects:
- kind: User
  name: jane
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

RoleBinding同样可以引用ClusterRole来对当前namespace内用户,用户组或ServiceAccount进行授权,这种操作允许集群管理员在整个集群内定义一些通用的ClusterRole,然后在不同的namespace中使用RoleBinding来引用

例如,以下RoleBinding引用了一个ClusterRole,这个ClusterRole具有整个集群内对secrets的访问权限;但是其授权用户dave只能访问development空间中的secrets,因为RoleBinding定义在development命名空间

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: read-secrets
  namespace: development
subjects:
- kind: User
  name: dave
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: secret-reader
  apiGroup: rbac.authorization.k8s.io

使用ClusterRoleBinding可以对整个集群中的所有命名空间资源权限进行授权;以下ClusterRoleBinding样例展示了授权manager组内所有用户在全部命名空间中对secrets进行访问

kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: read-secrets-global
subjects:
- kind: Group
  name: manager
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: secret-reader
  apiGroup: rbac.authorization.k8s.io

Resources

kubernetes集群内一些资源一般以其名称字符串来表示,这些字符串一般会在API的URL地址中出现,同时某些资源也会包含子资源,例如logs资源就属于pods的子资源,API中URL样例如下
GET /api/v1/namespaces/{namespace}/pods/{name}/log
如果要在RBAC授权模型中控制这些子资源的访问权限,可以通过/分隔符来实现,以下是一个定义pods资源logs访问权限的Role定义样例

kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  namespace: default
  name: pod-and-pod-logs-reader
rules:
- apiGroups: [""]
  resources: ["pods","pods/log"]
  verbs: ["get","list"]

to subjects

RoleBinding 和ClusterRoleBinding可将Role绑定到Subjects;Subjects可以使groups/users/service accounts

subjects中Users使用字符串表示,它可以是一个普通的名字字符串,如"alice";有也可以是email格式的邮箱;甚至是一组字符串形式的数字id,但是Users的前缀system;是系统保留的,集群管理员应该确保普通用户不会使用这个前缀格式
Groups书写与Users相同,都为一个字符串,并且没有特定的格式要求

实践:创建一个用户只能管理dev空间

{
    "CN": "devuser",
    "hosts": [],
    "key": {
        "algo": "rsa",
        "size": 2048
    },
    "names": [
        {
            "C": "CN",
            "ST": "Beijing",
            "L": "Beijing",
            "O": "k8s",
            "OU": "System"
        }
    ]
}
# 下载证书生成工具
wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64
mv cfssl-certinfo_linux-amd64 /usr/local/bin/cfssl-certinfo

wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
mv cfssljson_linux-amd64 /usr/local/bin/cfssljson

wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
mv cfssl_linux-amd64 /usr/local/bin/cfssl

cfssl gencert -ca=ca.crt -ca-key=ca.key -profile=kubernetes ~/Desktop/k8s/taint/cert/devuser/devuser-csr.json | cfssljson -bare devuser

# 设置集群参数
export KUBE_APISERVER="https://172.16.21.235:6443"
kubectl config set-cluster kubernetes  --certificate-authority=/etc/kubernetes/pki/ca.crt --embed-certs=true --server=${KUBE_APISERVER} --kubeconfig=devuser.kubeconfig
# 设置客户端认证参数
kubectl config set-credentials devuser --client-certificate=/etc/kubernetes/pki/devuser.pem --client-key=/etc/kubernetes/pki/devuser-key.pem --embed-certs=true --kubeconfig=devuser.kubeconfig
# 设置上下文参数
kubectl config set-context kubernetes --cluster=kubernetes --user=devuser --namespace=dev --kubeconfig=devuser.kubeconfig

# 设置默认上下文
kubectl conifg use-context kubernetes --kubeconfig=config
cp -f ./devuser.kubeconfig /root/.kube/config

kubectl create rolebinding devuser-admin-binding --clusterrole=admin --user=devuser --namespace=dev

准入控制

准入控制是API Server的插件集合,通过添加不同的插件,实现额外的准入控制规则。甚至于API Server的一些主要的功能都需要通过Admission Controllers实现,比如ServiceAccount

官方文档上有一份针对不同版本的准入控制器推荐列表,其中最新的1.14的推荐列表是

  • NamespaceLifecycle: 防止在不存在的namespace上创建对象,防止删除系统预置namespace,删除namespace时,连带删除它的所有资源对象
  • LimitRanger:确保请求的资源不会超过资源所有Namespace的LimitRange的限制
  • ServiceAccount:实现了自动添加的ServiceAccount
  • ResourceQuota:确保请求的资源不会超过资源的ResourceQuota限制

部署Helm

Helm本质是让K8s的应用管理可配置,能动态生成,通过动态生成K8s资源清单文件。然后调用Kubectl自动执行K8s资源部署

Helm是官方提供的类似于YUM的包管理器,是部署环境的流程封装

  • chart是创建一个应用的信息集合,包括各种Kubernetes对象的配置模板,参数定义,依赖关系,文档说明等。chart是应用部署的自包含逻辑单元。可以将chart想象成apt、yum中的软件安装包
  • release是chart的运行实例,代表了一个正在运行的应用。当chart被安装到Kubernetes集群,就生成一个release。chart能够多次安装到同一个集群。每次安装都是一个release

Helm包含两个组件:Helm客户端和Tiller服务器

Helm客户端负责chart和release的创建和管理以及和Tiller的交互。Tiller服务器运行在kubernetes集群中,它会处理Helm客户端的请求,与Kubernetes API Server交互

安装

github下载:https://github.com/helm/helm/releases
cd linux-amd64/
cp helm /usr/local/bin/
chmod +x /usr/local/bin/helm

为了安装服务端tiller,还需要在这台机器上配置好kubectl工具和kubeconfig文件,确保kubectl工具可以在这台机器上访问apiserver且正常使用。这里的node1节点以及配置好的kubectl

因为Kubernetes APIServer开启了RBAC访问控制,所以需要创建tiller使用的service account:tiller并分配合适的角色给它。详细内容可以查看Helm文档。这里直接分配cluster-admin这个集群内置的ClusterRole给它。创建rbac-config.yaml文件:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: tiller
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: tiller
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
  - kind: ServiceAccount
    name: tiller
    namespace: kube-system
kubectl create -f rbac-config.yaml
helm init --service-account tiller --skip-refresh

image.png
image.png

helm version

image.png

Helm自定义模板

./Chart.yaml

name: hello-world
version: 1.0.0
cat << 'EOF' > ./templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-world
spec:
  replicas: 1
  selector:
    matchLabels:
      app: hello-world
  template:
    metadata:
      labels:
        app: hello-world
    spec:
      containers:
      - name: hello-world
        image: nginx
        imagePullPolicy: IfNotPresent
        ports:
          - containerPort: 80
            protocol: TCP
EOF
cat <<'EOF'>./templates/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: hello-world
spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
  selector:
    app: hello-world
EOF
helm install . # build当前文件

image.png

# 配置提现在配置文件 values.yaml
cat <<'EOF' > ./values.yaml
image:
  repository: gcr.io/google-samples/node-hello
  tag: '1.0'
EOF
# 这个文件中定义的值,在模板文件中可以通过.Values对象访问到
cat <<'EOF' > ./templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-world
spec:
  replicas: 1
  selector:
    matchLabels:
      app: hello-world
  template:
    metadata:
      labels:
        app: hello-world
    spec:
      containers:
      - name: hello-world
        image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
        imagePullPolicy: IfNotPresent
        ports:
          - containerPort: 80
            protocol: TCP
EOF
在values.yaml中的值可以被部署release时用到的参数 --values YAML_FILE_PATH 或 --set key1=value1,key2=value2覆盖掉
helm install --set image.tag='latest'

# 升级版本
helm upgrade halting-umbrellabird .

# 真正删除
helm delete --purge umbrellabird

# 列出已删除
herm list --deleted

# 回滚
helm rollback halting-umbrellabird 1

# 尝试运行
helm install --dry-run .
  • 本文作者: Dante
  • 本文链接: https://gaodongfei.com/archives/k8s操作指南
  • 版权声明: 本博客所有文章除特别声明外,均采用CC BY-NC-SA 3.0 许可协议。转载请注明出处!
# kubernetes
ubuntu安装k8s
docker配置
  • 文章目录
  • 站点概览
Dante

Dante

119 日志
5 分类
5 标签
RSS
Creative Commons
0%
© 2023 Dante
由 Halo 强力驱动
|
主题 - NexT.Pisces v5.1.4
沪ICP备2020033702号