华为云用户手册

  • LoadBalancer类型的Service 现在您知道可以创建ClusterIP类型的Service,通过Service的IP可以访问到Service后端的Pod。 云容器实例同时还支持创建LoadBalancer类型的Service,将增强型ELB实例与Service绑定,这样访问ELB实例的流量就会访问到Service。 ELB实例根据IP地址不同可以分为私网ELB实例和公网ELB实例,区别在于公网ELB实例绑定了一个公网IP,您可以根据需要选择。您可以调用创建负载均衡器(增强型)创建ELB实例,更方便的方法是通过ELB控制台创建增强型ELB实例。 ELB实例必须与Service在同一个VPC内,否则无法绑定。 跨namespace不支持service或ELB域名访问,只能通过ELB内网IP:端口访问。 图3 LoadBalancer Service 下面是一个创建LoadBalancer类型的Service。创建完成后,可以通过ELB的IP:Port访问到后端Pod。 apiVersion: v1 kind: Service metadata: name: nginx annotations: kubernetes.io/elb.id: 77e6246c-a091-xxxx-xxxx-789baa571280 # ELB的ID spec: selector: app: nginx ports: - name: service0 targetPort: 80 port: 8080 # ELB访问端口 protocol: TCP type: LoadBalancer # Service的类型
  • 直接访问Pod的问题 负载创建完成后,如何访问负载呢?访问负载实际上就是访问Pod,但是直接访问Pod会有如下几个问题: Pod会随时被Deployment这样的控制器删除重建,那访问Pod的结果就会变得不可预知。 Pod的IP地址是在Pod启动后才被分配,在启动前并不知道Pod的IP地址。 应用往往都是由多个运行相同镜像的一组Pod组成,一个个Pod的访问也变得不现实。 举个例子,假设有这样一个应用程序,使用Deployment创建了前台和后台,前台会调用后台做一些计算处理,如图1所示。后台运行了3个Pod,这些Pod是相互独立且可被替换的,当Pod出现状况被重建时,新建的Pod的IP地址是新IP,前台的Pod无法直接感知。 图1 负载间访问
  • Service是如何工作的 Kubernetes中的Service对象就是用来解决上述Pod访问问题的。Service有一个固定IP地址,Service将访问他的流量转发给Pod,具体转发给哪些Pod通过Label来选择,而且Service可以给这些Pod做负载均衡。 那么对于上面的例子,通过为前后台添加两个Service,通过Service来访问Pod,这样前台Pod就无需感知后台Pod的变化,如图2所示。 图2 通过Service访问Pod
  • 约束与限制 一个Pod只能绑定一个EIP。 绑定EIP的Pod,如果要被公网成功访问,需要添加放通相应公网请求流量的安全组规则。 EIPPool正在被Pod使用时,不支持直接删除EIPPool,需删除关联Pod,再删除EIPPool。 EIPPool为namespace级别资源,不可跨namespace使用。 工作负载滚动升级时,默认策略是逐步创建新Pod然后删除旧Pod(请参见升级策略),则可能会由于EIPPool中EIP数量不足而升级失败。建议:EIPPool池的大小略大于使用该EIPPool的所有的Deployment副本数之和,或者maxSurge配置为0,可支持工作负载先减后增滚动升级。
  • 更新EIPPool 考虑到用户实际场景,EIPPool对象当前只允许用户调整EIP的数量,即对EIPPool进行扩缩容。用户如果需要调整EIP其他参数,可新建EIPPool对象后在负载配置中替换即可。 EIPPool缩容时,如果EIP资源被占用,则不会删除对应的EIP,直到占用解除。 以动态创建的eippool-demo1为例,将amount:3改为amount: 5。 apiVersion: crd.yangtse.cni/v1 kind: EIPPool metadata: name: eippool-demo1 namespace: xxx spec: amount: 5 # EIP资源池中的EIP数量 eipAttributes: # EIP的一些属性 ... 执行以下命令,查看EIPPool详情,-n表示EIPPool所在的命名空间。 回显信息中名称为eippool-demo1的EIPPool,USAGE由0/3更新为0/5,表示EIPPool更新成功。 # kubectl get eippool -n $namespace_name NAME EIPS USAGE AGE eippool-demo1 0/5 39m
  • Deployment如何控制Pod 继续查询Pod,如下所示。 $ kubectl get pods -n $namespace_name NAME READY STATUS RESTARTS AGE nginx-7f98958cdf-tdmqk 1/1 Running 0 13s nginx-7f98958cdf-txckx 1/1 Running 0 13s 如果删掉一个Pod,您会发现立马会有一个新的Pod被创建出来,如下所示,这就是前面所说的Deployment会确保有2个Pod在运行,如果删掉一个,Deployment会重新创建一个,如果某个Pod崩溃或有什么问题,Deployment会自动拉起这个Pod。 $ kubectl delete pod nginx-7f98958cdf-txckx -n $namespace_name $ kubectl get pods -n $namespace_name NAME READY STATUS RESTARTS AGE nginx-7f98958cdf-tdmqk 1/1 Running 0 21s nginx-7f98958cdf-tesqr 1/1 Running 0 21s 看到有如下两个名为nginx-7f98958cdf-tdmqk和nginx-7f98958cdf-tesqr的Pod, 其中nginx是直接使用Deployment的名称,-7f98958cdf-tdmqk和-7f98958cdf-tesqr是kubernetes随机生成的后缀。 您也许会发现这两个后缀中前面一部分是相同的,都是7f98958cdf,这是因为Deployment不是直接控制Pod的,Deployment是通过一种名为ReplicaSet的控制器控制Pod,通过如下命令可以查询ReplicaSet,其中rs是ReplicaSet的缩写。 $ kubectl get rs -n $namespace_name NAME DESIRED CURRENT READY AGE nginx-7f98958cdf 3 3 3 1m 这个ReplicaSet的名称为nginx-7f98958cdf,后缀-7f98958cdf也是随机生成的。 Deployment控制Pod的方式如图1所示,Deployment控制ReplicaSet,ReplicaSet控制Pod。 图1 Deployment通过ReplicaSet控制Pod 如果使用kubectl describe命令查看Deployment的详情,您就可以看到ReplicaSet,如下所示,可以看到有一行 NewReplicaSet: nginx-7f98958cdf (2/2 replicas created),而且 Events 里面事件确是把ReplicaSet的实例扩容到2个。在实际使用中您也许不会直接操作ReplicaSet,但了解Deployment通过控制ReplicaSet来控制Pod会有助于您定位问题。 $ kubectl describe deploy nginx -n $namespace_name Name: nginx Namespace: default CreationTimestamp: Sun, 16 Dec 2018 19:21:58 +0800 Labels: app=nginx ... NewReplicaSet: nginx-7f98958cdf (2/2 replicas created) Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ScalingReplicaSet 5m deployment-controller Scaled up replica set nginx-7f98958cdf to 2
  • 升级 在实际应用中,升级是一个常见的场景,Deployment能够很方便的支撑应用升级。 Deployment 可以设置不同的升级策略,有如下两种。 RollingUpdate:也就是滚动升级(逐步创建新Pod然后删除旧Pod),也是默认策略 Recreate:也就是先把当前Pod删掉再重新创建Pod Deployment的升级可以是声明式的,也就是说只需要修改Deployment的YAML定义即可,比如使用kubectl edit命令将上面Deployment中的镜像修改为nginx:alpine。修改完成后再查询ReplicaSet和Pod,发现创建了一个新的ReplicaSet,Pod也重新创建了。 $ kubectl edit deploy nginx -n $namespace_name $ kubectl get rs -n $namespace_name NAME DESIRED CURRENT READY AGE nginx-6f9f58dffd 2 2 2 1m nginx-7f98958cdf 0 0 0 48m $ kubectl get pods -n $namespace_name NAME READY STATUS RESTARTS AGE nginx-6f9f58dffd-tdmqk 1/1 Running 0 21s nginx-6f9f58dffd-tesqr 1/1 Running 0 21s Deployment可以通过maxSurge 和 maxUnavailable两个参数控制升级过程中同时重新创建Pod的比例,这在很多时候是非常有用,配置如下所示。 spec: strategy: rollingUpdate: maxSurge: 1 maxUnavailable: 0 type: RollingUpdate maxSurge:与Deployment中spec.replicas相比,可以有多少个Pod存在,默认值是25%,比如spec.replicas为 4,那升级过程中就不能超过5个 Pod存在,即按1个的步伐升级,实际升级过程中会换算成数字,且换算会向上取整。这个值也可以直接设置成数字。 maxUnavailable:与Deployment中spec.replicas相比,可以有多少个Pod失效,也就是删除的比例,默认值是25%,比如spec.replicas为 4,那升级过程中就至少有3个Pod存在,即删除Pod 的步伐是 1。同样这个值也可以设置成数字。 在前面的例子中,由于spec.replicas是2,如果maxSurge和maxUnavailable都为默认值25%,那实际升级过程中,maxSurge允许最多3个 Pod 存在(向上取整,2*1.25=2.5,取整为3),而 maxUnavailable 则不允许有 Pod Unavailable(向上取整,2*0.75=1.5,取整为2),也就是说在升级过程中,一直会有2个Pod处于运行状态,每次新建一个Pod,等这个Pod创建成功后再删掉一个旧Pod,直至Pod全部为新Pod。
  • 回滚 回滚也称为回退,即当发现升级出现问题时,让应用回到老的版本。Deployment可以非常方便的回滚到老版本。 例如上面升级的新版镜像有问题,可以执行kubectl rollout undo命令进行回滚。 $ kubectl rollout undo deployment nginx -n $namespace_name deployment "nginx" rolled back Deployment之所以能如此容易的做到回滚,是因为Deployment是通过ReplicaSet控制Pod的,升级后之前ReplicaSet都一直存在,Deployment回滚做的就是使用之前的ReplicaSet再次把Pod创建出来。Deployment中保存ReplicaSet的数量可以使用revisionHistoryLimit参数限制,默认值为10。
  • 创建Deployment 以下示例为创建一个名为nginx的Deployment负载,使用nginx:latest镜像创建两个Pod,每个Pod占用500m core CPU、1G内存。 apiVersion: apps/v1 # 注意这里与Pod的区别,Deployment是apps/v1而不是v1 kind: Deployment # 资源类型为Deployment metadata: name: nginx # Deployment的名称 spec: replicas: 2 # Pod的数量,Deployment会确保一直有2个Pod运行 selector: # Label Selector matchLabels: app: nginx template: # Pod的定义,用于创建Pod,也称为Pod template metadata: labels: app: nginx spec: volumes: - name: cci-sfs-test # sfs卷的名称 persistentVolumeClaim: claimName: cci-sfs-test containers: - image: nginx:latest name: container-0 resources: limits: cpu: 500m memory: 1024Mi requests: cpu: 500m memory: 1024Mi volumeMounts: - name: cci-sfs-test mountPath: /tmp/sfs0/krlp2k8j # sfs卷的容器内挂载路径 imagePullSecrets: # 拉取镜像使用的证书,必须为imagepull-secret - name: imagepull-secret 从这个定义中可以看到Deployment的名称为nginx,spec.replicas定义了Pod的数量,即这个Deployment控制2个Pod;spec.selector是Label Selector(标签选择器),表示这个Deployment会选择Label为app=nginx的Pod;spec.template是Pod的定义,内容与Pod中的定义完全一致。 将上面Deployment的定义保存到deployment.yaml文件中,使用kubectl创建这个Deployment。 使用kubectl get查看Deployment和Pod,可以看到DESIRED值为2,这表示这个Deployment期望有2个Pod,CURRENT也为2,这表示当前有2个Pod,AVAILABLE为2表示有2个Pod是可用的。 $ kubectl create -f deployment.yaml -n $namespace_name $ kubectl get deployment -n $namespace_name NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE nginx 2 2 2 2 8s
  • 环境变量 环境变量是容器运行环境中设定的一个变量。 环境变量为应用提供极大的灵活性,您可以在应用程序中使用环境变量,在创建容器时为环境变量赋值,容器运行时读取环境变量的值,从而做到灵活的配置,而不是每次都重新编写应用程序制作镜像。 另外,您还可以使用ConfigMap和Secret作为环境变量,详细信息请参见使用ConfigMap和Secret提高配置灵活性。 环境变量的使用方法如下所示,配置spec.containers.env字段即可。 apiVersion: v1 kind: Pod metadata: name: nginx spec: containers: - image: nginx:1 name: container-0 resources: limits: cpu: 500m memory: 1024Mi requests: cpu: 500m memory: 1024Mi env: # 环境变量 - name: env_key value: env_value - name: pod_name valueFrom: # 引用Pod的名称 fieldRef: fieldPath: metadata.name - name: pod_ip valueFrom: # 引用Pod的IP地址 fieldRef: fieldPath: status.podIP imagePullSecrets: - name: imagepull-secret 父主题: Pod
  • 配置有效的Liveness Probe liveness probe应该检查什么 一个好的liveness probe应该检查应用内部所有关键部分是否健康,并使用一个专有的URL访问,例如 /health,当访问 /health 时执行这个功能,然后返回对应结果。这里要注意不能做鉴权,不然 probe 就会一直失败导致陷入重启的死循环。 另外检查只能限制在应用内部,不能检查依赖外部的部分,例如当前端web server不能连接数据库时,这个就不能看成web server不健康。 liveness probe必须轻量 liveness probe不能占用过多的资源,且不能占用过长的时间,否则所有资源都在做健康检查,这就没有意义了。例如Java应用,就最好用HTTP GET方式,如果用 Exec 方式,JVM启动就占用了非常多的资源。
  • HTTP GET HTTP GET方式是最常见的探测方法,其具体机制是向容器发送HTTP GET请求,如果probe收到2xx或3xx,说明容器是健康的,定义方法如下所示。 apiVersion: v1 kind: Pod metadata: name: liveness-http spec: containers: - name: liveness image: k8s.gcr.io/liveness args: - /server livenessProbe: # liveness probe httpGet: # HTTP GET定义 path: /healthz port: 8080 创建这个Pod。 $ kubectl create -f liveness-http.yaml -n $namespace_name pod/liveness-http created 如上,这个probe往容器的8080端口发送HTTP GET请求,上面的程序会在第五次请求会返回500状态码,这时Kubernetes会去重启容器。 查看Pod详情。 $ kubectl describe po liveness-http -n $namespace_name Name: liveness-http ...... Containers: container-0: ...... State: Running Started: Mon, 12 Nov 2018 22:57:28 +0800 Last State: Terminated Reason: Error Exit Code: 137 Started: Mon, 12 Nov 2018 22:55:40 +0800 Finished: Mon, 12 Nov 2018 22:57:27 +0800 Ready: True Restart Count: 1 Liveness: http-get http://:8080/ delay=0s timeout=1s period=10s #success=1 #failure=3 ...... Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 3m5s default-scheduler Successfully assigned default/pod-liveness to node2 Normal Pulling 74s (x2 over 3m4s) kubelet, node2 pulling image "pod-liveness" Normal Killing 74s kubelet, node2 Killing container with id docker://container-0:Container failed liveness probe.. Container will be killed and recreated. 可以看到Pod当前状态是Running,Last State是Terminated,Restart Count为1,说明已经重启1次,另外从事件中也可以看到 Killing container with id docker://container-0:Container failed liveness probe.. Container will be killed and recreated. 另外,容器Kill后会重新创建一个新容器,不只是之前的容器重启。
  • Exec Exec即执行具体命令,具体机制是probe执行容器中的命令并检查命令退出的状态码,如果状态码为0则说明健康,定义方法如下所示。 apiVersion: v1 kind: Pod metadata: labels: test: liveness name: liveness-exec spec: containers: - name: liveness image: busybox args: - /bin/sh - -c - touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600 livenessProbe: # liveness probe exec: # Exec定义 command: - cat - /tmp/healthy 上面定义在容器中执行cat /tmp/healthy命令,如果成功执行并返回0,则说明容器是健康的。
  • Liveness Probe高级配置 上面liveness-http的describe命令回显中有如下行。 Liveness: http-get http://:8080/ delay=0s timeout=1s period=10s #success=1 #failure=3 这一行表示liveness probe的具体参数配置,其含义如下: delay=0s 表示容器启动后立即开始探测,没有延迟时间 timeout=1s 表示容器必须在1s内做出相应反馈给probe,否则视为探测失败 period=10s 表示每10s探测一次 #success=1 表示探测连续1次成功表示成功 #failure=3 表示探测连续3次失败后会重启容器 这些是创建时默认设置的,您也可以手动配置,如下所示。 apiVersion: v1 kind: Pod metadata: name: liveness-http spec: containers: - image: k8s.gcr.io/liveness livenessProbe: httpGet: path: / port: 8080 initialDelaySeconds: 10 # 容器启动后多久开始探测 timeoutSeconds: 2 # 表示容器必须在2s内做出相应反馈给probe,否则视为探测失败 periodSeconds: 30 # 探测周期,每30s探测一次 successThreshold: 1 # 连续探测1次成功表示成功 failureThreshold: 3 # 连续探测3次失败表示失败 initialDelaySeconds一般要设置大于0,这是由于很多情况下容器虽然启动成功,但应用就绪也需要一定的时间,需要等就绪时间之后才能返回成功,否则就会导致probe经常失败。 另外failureThreshold可以设置多次循环探测,这样在实际应用中健康检查的程序就不需要多次循环,这一点在开发应用时需要注意。
  • 存活探针 Kubernetes提供了自愈的能力,具体就是能感知到容器崩溃,然后能够重启这个容器。但是有时候例如Java程序内存泄漏了,程序无法正常工作,但是JVM进程却是一直运行的,对于这种应用本身业务出了问题的情况,kubernetes提供了liveness probe机制,通过检测容器响应是否正常来决定是否重启,这是一种很好的健康检查机制。 毫无疑问,每个pod最好都定义liveness probe,否则Kubernetes无法感知Pod是否正常运行。 当前云容器实例支持如下两种探测机制。 HTTP GET:向容器发送HTTP GET请求,如果probe收到2xx或3xx,说明容器是健康的。 Exec:probe执行容器中的命令并检查命令退出的状态码,如果状态码为0则说明健康。
  • 路由到多个服务 Ingress可以同时路由到多个服务,配置如下所示。 当访问“http://foo.bar.com/foo”时,访问的是“s1:80”后端。 当访问“http://foo.bar.com/bar”时,访问的是“s2:80”后端。 spec: rules: - host: foo.bar.com # host地址 http: paths: - path: "/foo" backend: serviceName: s1 servicePort: 80 - path: "/bar" backend: serviceName: s2 servicePort: 80
  • 创建Ingress 使用http协议创建Ingress 下面例子中,关联的backend为“nginx:8080”,当访问“http://10.10.10.10:6071/”时,流量转发“nginx:8080”对应的Service,从而将流量转发到对应负载中的Pod。 apiVersion: extensions/v1beta1 # Ingress的版本 kind: Ingress metadata: name: nginx labels: app: nginx isExternal: "true" # 必选参数,取值必须为 "true" zone: data # 数据平面模式,必选参数,取值必须为data annotations: kubernetes.io/elb.id: 2d48d034-6046-48db-8bb2-53c67e8148b5 # ELB实例的ID,必选参数 kubernetes.io/elb.ip: 192.168.137.182 # ELB实例的IP,可选参数 kubernetes.io/elb.port: '6071' # ELB实例的端口,必选参数 spec: rules: # 路由规则 - http: # 使用http协议 paths: - path: / # 路由 backend: serviceName: nginx # 转发到的Service名称 servicePort: 8080 # 转发到的Service端口 Ingress中还可以设置外部域名,这样您就可以通过域名来访问到ELB,进而访问到后端服务。 域名访问依赖于域名解析,需要您将域名解析指向ELB实例的IP地址,例如您可以使用云解析服务 DNS来实现域名解析。 spec: rules: - host: www.example.com # 域名 http: paths: - path: / backend: serviceName: nginx servicePort: 80 使用https协议创建Ingress 下面例子中,关联的backend为“nginx:8080”,当访问“https://10.10.10.10:6071/”时,流量转发“nginx:8080”对应的Service,从而将流量转发到对应负载中的Pod。 apiVersion: extensions/v1beta1 kind: Ingress metadata: annotations: kubernetes.io/elb.id: 2d48d034-6046-48db-8bb2-53c67e8148b5 kubernetes.io/elb.ip: 192.168.137.182 kubernetes.io/elb.port: '6071' labels: app: nginx isExternal: 'true' zone: data name: nginx spec: rules: - http: paths: - backend: serviceName: nginx servicePort: 8080 path: / tls: - secretName: cci-sslcertificate-20214221 # 上传的SSL证书的名称
  • 启动命令 启动容器就是启动主进程,但有些时候,启动主进程前,需要一些准备工作。比如MySQL类的数据库,可能需要一些数据库配置、初始化的工作,这些工作要在最终的MySQL服务器运行之前解决。这些操作,可以在制作镜像时通过在Dockerfile文件中设置ENTRYPOINT或CMD来完成,如下所示的Dockerfile中设置了ENTRYPOINT ["top", "-b"]命令,其将会在容器启动时执行。 FROM ubuntu ENTRYPOINT ["top", "-b"] 调用接口时,只需配置pod的containers.command参数,该参数是list类型,第一个参数为执行命令,后面均为命令的参数。 apiVersion: v1 kind: Pod metadata: name: Ubuntu spec: containers: - image: Ubuntu name: container-0 resources: limits: cpu: 500m memory: 1024Mi requests: cpu: 500m memory: 1024Mi command: # 启动命令 - top - "-b" imagePullSecrets: - name: imagepull-secret 父主题: Pod
  • 创建CronJob 相比Job,CronJob就是一个加了定时的Job,CronJob执行时是在指定的时间创建出Job,然后由Job创建出Pod。 apiVersion: batch/v1beta1 kind: CronJob metadata: name: cronjob-example namespace: cci-namespace-test1 spec: schedule: "0,15,30,45 * * * *" # 定时相关配置 jobTemplate: # Job的定义 spec: template: spec: restartPolicy: OnFailure containers: - name: main image: pi cron的格式从前到后就是: Minute Hour Day of month Month Day of week 如 "0,15,30,45 * * * * " ,前面逗号隔开的是分钟,后面第一个* 表示每小时,第二个 * 表示每个月的哪天,第三个表示每月,第四个表示每周的哪天。 如果你想要每个月的第一天里面每半个小时执行一次,那就可以设置为" 0,30 * 1 * * " 如果你想每个星期天的3am执行一次任务,那就可以设置为 "0 3 * * 0"。 更详细的cron格式说明请参见https://zh.wikipedia.org/wiki/Cron。
  • 创建Job 以下是一个Job配置,其计算π到2000位并打印输出。Job结束需要运行50个Pod,这个示例中就是打印π 50次,并行运行5个Pod,Pod如果失败最多重试5次。 apiVersion: batch/v1 kind: Job metadata: name: pi-with-timeout namespace: cci-namespace-test1 spec: completions: 50 # 运行的次数,即Job结束需要成功运行的Pod个数 parallelism: 5 # 并行运行Pod的数量,默认为1 backoffLimit: 5 # 表示失败Pod的重试最大次数,超过这个次数不会继续重试。 activeDeadlineSeconds: 10 # 表示Pod超期时间,一旦达到这个时间,Job即其所有的Pod都会停止。 template: # Pod定义 spec: containers: - name: pi image: perl command: - perl - "-Mbignum=bpi" - "-wle" - print bpi(2000) restartPolicy: Never 根据completions和parallelism的设置,可以将Job划分为以下几种类型。 表1 任务类型 Job类型 说明 使用示例 一次性Job 创建一个Pod直至其成功结束 数据库迁移 固定结束次数的Job 依次创建一个Pod运行直至completions个成功结束 处理工作队列的Pod 固定结束次数的并行Job 依次创建多个Pod运行直至completions个成功结束 多个Pod同时处理工作队列 并行Job 创建一个或多个Pod直至有一个成功结束 多个Pod同时处理工作队列
  • 创建PVC 通过如下定义创建PVC,这个定义申请了一块大小为100G的SAS型云硬盘。 如果需要创建加密类型的云硬盘存储卷,在metadata.annotations中增加paas.storage.io/cryptKeyId字段即可。 apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pvc-evs namespace: namespaces-test annotations: { paas.storage.io/cryptKeyId: ee9b610c-e356-11e9-aadc-d0efc1b3bb6b } spec: accessModes: - ReadWriteMany resources: requests: storage: 100Gi storageClassName: sas accessModes为存储访问模式,支持如下3种模式: ReadWriteOnce:可以被单个节点以读/写模式挂载 ReadOnlyMany:可以被多个节点以只读模式挂载 ReadWriteMany:可以被多个节点以读/写模式挂载 storageClassName表示申请的存储类型,当前支持如下4个参数: sas:SAS(高I/O)型EVS硬盘 ssd:SSD(超高I/O)型EVS硬盘 nfs-rw:标准文件协议类型SFS文件存储 csi-sfs:SFS 3.0容量型弹性文件服务 通过如下定义创建PVC,这个定义申请了一块大小为100G的文件存储。 如果需要创建加密类型的文件存储卷,在metadata.annotations中增加paas.storage.io/cryptKeyId、paas.storage.io/cryptAlias和paas.storage.io/cryptDomainId即可。 apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pvc-sfs namespace: namespace-test annotations: { paas.storage.io/cryptKeyId: ee9b610c-e356-11e9-aadc-d0efc1b3bb6b paas.storage.io/cryptAlias: sfs/default paas.storage.io/cryptDomainId: d6912480-c3d6-4e9e-8c70-38afeea434c3 volume.beta.kubernetes.io/storage-provisioner: flexvolume-huawei.com/fuxinfs } spec: accessModes: - ReadWriteMany resources: requests: storage: 100Gi storageClassName: nfs-rw
  • 使用PVC 使用PVC申请到存储资源后,您可以在Pod中使用Volume来关联PVC,并将Volume挂载到容器中使用。 下面是的示例中说明了PVC如何在Pod中使用,这个Pod定义了一个名为“pvc-test-example”的Volume,并将这个Volume挂载到容器的“/tmp/volume0”路径,这样您写入到/tmp的数据就是写到名为pvc-test的PVC中。 写入上面申请的sas型云硬盘中 apiVersion: v1 kind: Pod metadata: name: nginx labels: app: nginx spec: containers: - image: nginx:latest name: container-0 resources: limits: cpu: 500m memory: 1024Mi requests: cpu: 500m memory: 1024Mi volumeMounts: - mountPath: "/tmp/volume0" # 将PVC挂载到容器的/tmp/volume0路径 name: pvc-test-example # Volume的名称 volumes: # 定义Volume,关联PVC - name: pvc-test-example persistentVolumeClaim: claimName: pvc-test # PVC的名称 imagePullSecrets: - name: imagepull-secret 写入上面申请的文件存储(storageClassName设置为nfs-rw型)中。 当创建PVC申请文件存储(storageClassName设置为nfs-rw型)时,在volumeMounts中可设置挂载子路径,即文件存储根路径下子路径。 apiVersion: v1 kind: Pod metadata: name: nginx labels: app: nginx spec: containers: - image: nginx:latest name: container-0 resources: limits: cpu: 500m memory: 1024Mi requests: cpu: 500m memory: 1024Mi volumeMounts: - mountPath: "/tmp/volume0" # 将PVC挂载到容器的/tmp/volume0路径 subPath: "abc" # 文件存储根路径下子路径,如果不存在会自动在文件存储中创建。该子路径必须为相对路径。 name: pvc-test-example # Volume的名称 volumes: # 定义Volume,关联PVC - name: pvc-test-example persistentVolumeClaim: claimName: pvc-test # PVC的名称 imagePullSecrets: - name: imagepull-secret
  • 添加Label Label的形式为key-value形式,使用非常简单,如下,为Pod设置了app=nginx和env=prod两个Label。 apiVersion: v1 kind: Pod metadata: name: nginx labels: # 为Pod设置两个Label app: nginx env: prod spec: containers: - image: nginx:latest name: container-0 resources: limits: cpu: 500m memory: 1024Mi requests: cpu: 500m memory: 1024Mi imagePullSecrets: - name: imagepull-secret Pod有了Label后,在查询Pod的时候带上 --show-labels 就可以看到Pod的Label。 $ kubectl get pod --show-labels -n $namespace_name NAME READY STATUS RESTARTS AGE LABELS nginx 1/1 Running 0 50s app=nginx,env=prod 还可以使用 -L 只查询某些固定的Label。 $ kubectl get pod -L app,env -n $namespace_name NAME READY STATUS RESTARTS AGE APP ENV nginx 1/1 Running 0 1m nginx prod 对已存在的Pod,可以直接使用 kubectl label 命令直接添加Label。 $ kubectl label po nginx creation_method=manual -n $namespace_name pod "nginx" labeled $ kubectl get pod --show-labels -n $namespace_name NAME READY STATUS RESTARTS AGE LABELS nginx 1/1 Running 0 50s app=nginx,env=prod,creation_method=manual
  • 修改Label 对于已存在的Label,如果要修改的话,需要在命令中带上--overwrite,如下所示。 $ kubectl label po nginx env=debug --overwrite -n $namespace_name pod "nginx" labeled $ kubectl get pod --show-labels -n $namespace_name NAME READY STATUS RESTARTS AGE LABELS nginx 1/1 Running 0 50s app=nginx,env=debug,creation_method=manual
  • 为什么需要Label 当资源变得非常多的时候,如何分类管理就非常重要了,Kubernetes提供了一种机制来为资源分类,那就是Label(标签)。Label非常简单,但是却很强大,Kubernetes中几乎所有资源都可以用Label来组织。 Label的具体形式是key-value的标记对,可以在创建资源的时候设置,也可以在后期添加和修改。 以Pod为例,当Pod变得多起来后,就显得杂乱且难以管理,如下图所示。 图1 没有分类组织的Pod 如果我们为Pod打上不同标签,那情况就完全不同了,如下图所示。 图2 使用Label组织的Pod
  • PersistentVolumeClaim(PVC) 云容器实例使用PVC申请并管理持久化存储,PVC可以让您无需关心底层存储资源如何创建、释放等动作,而只需要申明您需要何种类型的存储资源、多大的存储空间。 在实际使用中,您可以通过Pod中的Volume来关联PVC,通过PVC使用持久化存储,如图1所示。 图1 使用持久化存储 在云容器实例控制台,您可以导入已经创建的EVS、SFS和SFS Turbo,导入这些存储资源的同时会创建一个PVC用于这些存储资源。 您还可以在云容器实例控制台直接购买EVS和SFS,购买动作不仅购买实际的存储资源,同时还会创建PVC,也就是在这里购买就会直接导入到云容器实例中。
  • 操作步骤 账号A委托账号B以联邦用户的身份管理账号A中的资源,需要完成以下步骤: 创建委托(委托方操作) 登录委托方(账号A)IAM控制台创建委托,需要填写被委托方(账号B)的账号名称,并授予被委托方(账号B)云容器实例所有权限“CCI FullAccess”,拥有该权限的用户可以执行云容器实例所有资源的创建、删除、查询、更新操作。 为委托账号授权命名空间权限(委托方操作) 进入委托方(账号A)的CCI控制台,在权限管理页面为被委托方(账号B)授予命名空间下资源的权限,通过权限设置可以让不同的委托账号拥有操作指定Namespace下Kubernetes资源的权限。 联邦身份认证(被委托方操作) 登录被委托方(账号B),在被委托方(账号B)中进行联邦身份认证操作。 在委托联邦用户管理资源之前,需对被委托方进行联邦身份认证,联邦身份认证过程主要分为两步:建立互信关系并创建身份提供商和在华为云配置身份转换规则。 创建身份提供商时,会创建出默认的身份转换规则,用户需要单击“编辑规则”将默认的身份转换规则更新掉,或者将默认的身份转换规则删除,重新创建新的规则。如果默认的身份转换规则在没有删掉的情况下直接添加新规则,可能会匹配上这条默认规则,添加的新规则就会不生效。 分配委托权限(被委托方操作) 如果被委托方(账号B)下的子用户想要切换委托,就必须由被委托方(账号B)分配委托权限。因此,为了使得联邦用户拥有管理委托方(账号A)资源的权限,就需要被委托方(账号B)授予联邦用户所在用户组(federation_group)自定义策略“federation_agency”。“federation_group”用户组为联邦用户所在的用户组,也是配置身份转换规则时,写入规则中的联邦用户组。 切换角色(被委托方操作) 账号B以及分配了委托权限的联邦用户,可以切换角色至委托方账号A中,根据权限管理委托方的资源。
  • 使用Service方式访问-创建工作负载时设置 在云容器实例中,您只需要在创建负载时,填写服务名称和负载的端口配置,即可通过“服务名称:负载访问端口”访问到该负载。 服务名称:服务名称即Service的名称,Service是用于管理Pod访问的对象。Service的详细信息请参见https://support.huaweicloud.com/devg-cci/cci_05_0007.html。 安装coredns:coredns插件为您的其他负载提供内部域名解析服务,如果不安装coredns则无法通过“服务名称:负载访问端口”访问负载。 负载端口配置 协议:访问负载的通信协议,可选择TCP或UDP。 负载访问端口:负载提供的访问端口。 容器端口:容器监听的端口,负载访问端口映射到容器端口。
  • 配置说明 您需要拥有一个主账号,仅主账号、授予了CCI FullAccess权限的用户或拥有RBAC所有权限的用户,才可以对其他用户进行授权操作。 本例将对用户和用户组授予操作不同命名空间资源的权限,在您的实际业务中,您可根据业务需求仅对用户或用户组授予不同的权限。 本例仅用于给用户或用户组在未授权过的命名空间下新增权限,已授权的用户或用户组的权限可以在“权限管理”的列表“操作”栏中单击“编辑”进行修改。 当给用户或用户组添加多个权限时,多个权限会同时生效(取并集);为用户组设置的权限将作用于用户组下的全部用户。 在开启RBAC鉴权场景下,同类权限取并集,不同类权限取交集。例如,IAM细粒度鉴权中给用户组添加了多个权限,此时权限取最高权限,同理CCI权限管理给用户或用户组添加了多个权限,此时权限也取最高权限,即为同类权限取并集。当用户拥有CCI CommonOperations权限时,本可以创建无状态负载,但如该用户以及用户所在用户组未在目标Namespace下被赋予对应RBAC权限,则创建无状态负载会鉴权失败,即为不同类权限取交集。
  • 示例流程 命名空间是对一组资源和对象的抽象整合。在同一个集群内可创建不同的命名空间,不同命名空间中的数据彼此隔离,使得它们既可以共享同一个集群的服务,也能够互不干扰。命名空间的一个重要的作用是充当一个虚拟的集群,用于多种工作用途,满足多用户的使用需求。 本章节将沿用创建用户并授权使用CCI中创建的IAM用户“James”和用户组“开发人员组”进行说明,为IAM用户“James”和用户组“开发人员组”添加命名空间权限,可以参考如下操作: 步骤一:为IAM用户/用户组添加命名空间权限 步骤二:用户登录并验证权限
共100000条