问题描述
1)管理 Kubernetes 基础的工作负载(Workloads):「部署」和「POD」;
2)通过命令行和 YAML 文件,创建「部署」和「POD」;
3)以及如何「伸缩」和「更新」部署;
该笔记将记录:在 Kubernetes Cluster 中,部署演示使用的 Web 应用,以快速入门;
解决方案
清单文件格式
kubectl 可以非常简单的部署一个对象,但是更多的细节需要通过清单文件控制;
kind: Pod apiVersion: v1 metadata: name: mypod # 还可以包含 spec 字段 # spec: # ...
快速创建用于测试的网站(Nginx)
Run a Stateless Application Using a Deployment | Kubernetes
kubectl apply -f - <<EOF --- apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment spec: selector: matchLabels: app: nginx replicas: 1 template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.14.2 ports: - containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: nginx-service spec: # type: NodePort type: LoadBalancer ports: - port: 8080 targetPort: 80 selector: app: nginx EOF
Simple Website
MySQL
cat > mysql.yaml <<EOF --- apiVersion: apps/v1 kind: Deployment metadata: name: mysql spec: replicas: 1 selector: matchLabels: app: mysql template: metadata: labels: app: mysql spec: containers: - name: mysql image: mysql:5.7 ports: - containerPort: 3306 env: - name: MYSQL_ROOT_PASSWORD value: "123456" --- apiVersion: v1 kind: Service metadata: name: mysql spec: ports: - port: 3306 selector: app: mysql EOF kubectl apply -f mysql.yaml
Tomcat
cat > myweb.yaml <<EOF --- apiVersion: apps/v1 kind: Deployment metadata: name: myweb spec: replicas: 2 selector: matchLabels: app: myweb template: metadata: labels: app: myweb spec: containers: - name: myweb image: kubeguide/tomcat-app:v1 ports: - containerPort: 8080 env: - name: MYSQL_SERVICE_HOST value: 'mysql' - name: MYSQL_SERVICE_PORT value: '3306' --- apiVersion: v1 kind: Service metadata: name: myweb spec: ports: - port: 8080 selector: app: myweb EOF kubectl apply -f myweb.yaml
Ingress
cat > myweb-ingress.yaml <<EOF apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: name: myweb-ingress annotations: # use the shared ingress-nginx kubernetes.io/ingress.class: "nginx" spec: rules: - host: "k8s-ingress.example.xyz" http: paths: - path: / backend: serviceName: myweb servicePort: 8080 EOF kubectl apply -f ./myweb-ingress.yaml
访问页面
返回如下页面表示成功:
常见 Port 位置及含义
每个节点上都运行 kube-proxy 容器,它的作用是操作 iptables 规则,kube-proxy 会在防火墙上配置 DNAT 规则,将指定端口的访问传递给对应的容器;
在 Kubernetes 1.9.1 中,开始 beta 版本 IPVS 特性,也是在操作 Netfilter 进行流量转发;
在 Service 中
targetPort
在「Pod」中的容器的端口;
port
由「Service」暴露的端口。在容器内部使用,供容器之间访问;
nodePort
外部机器可访问的端口。在「Node」上暴露的端口,可以通过「IPAddress:Port」的形式直接访问;
在 Ingress 中
ServicePort
在 Ingress 中,能够看到对应关系,ServicePort 对于 Serivce 的 Port 参数;
常用命令汇总
更新 Deployment 的某个镜像:
# kubectl set image deployment/my-deployment mycontainer=myimage:latest
4.1. Creating a Deployment Using kubectl run
使用 kubectl run 命令创建部署:
# kubectl get deployment/ghost
可以通过选项指定部署参数:–env, –port, –command, –expose, –replicas
kubectl run ghost –image=ghost:0.9 –port=2368 –expose # 在 2368 端口启动 Ghost,并创建一个服务;
kubectl run mysql –image=mysql:5.5 –env=MYSQL_ROOT_PASSWORD=root # 使用 ROOT 密码启动 MySQL 服务;
kubectl run myshell –image=busybox –command — sh -c “sleep 135142” # 启动 Busybox 容器,并运行指定的命令;
4.2. Creating Objects from File Manifests
还可以通过清单文件创建:
下面是一个「命名空间」的清单文件的示例:
# myns.yaml apiVersion: v1 kind: namespace metadata: name: myns
使用kubectl create -f myns.yaml命令创建该对象;
还可以使用 URL 来创建:kubectl create -f https://example.com/path/to/foo.yaml
4.3. Writing a Pod Manifest from Scratch
从零编写一个「Pod」文件,Pod 是一个 /api/v1 的对象,和其他 Kubernetes 对象类似,清单文件包含以下字段:
kind:指定对象类型
metadata:提供对象相关的元数据
spec:指定对象的规则
Pod 的清单文件包含一组容器以及一组可选的卷,下面是一个简单的例子,只包含一个容器,不包含卷:
# mpod.yaml apiVersion: v1 kind: pod metadata: name: mPod spec: containers: - name: mPod image: nginx
使用kubectl create -f mpod.yaml创建该 POD;
与上述示例相比,真正的 Pod 的 API 规格要复杂得多。例如 POD 可以包含多个容器:
# mpod.yaml apiVersion: v1 kind: pod metadata: name: mPod spec: containers: - name: mPod image: nginx - name: mPod image: nginx
「Pod」中还可以包含「卷」的定义,用于在容器中加载数据,还可以探测容器的应用程序的健康状况;
更多关于规则字段的描述,以及 API 对象的所有规则,可以参考「Pods」手册;
不要单独创建「Pod」,应该创建「部署」对象来监管「Pod」,它会通过另外一个 ReplicaSet 的对象监控「Pod」;
4.4. Launching a Deployment Using a Manifest
使用 Deployment 控制应用的启动和监控;
# fan.yaml apiVersion: extensions/v1beta1 kind: Deployment metadata: name: fancyapp spec: replicas: 5 template: metadata: labels: app: fancy env: development spec: containers: - name: sise image: demo:0.5.- ports: - containerPort: 9876 env: - name: SIMPLE_SERVICE_VERSION value: "0.9"
可以看出,启动该应用的时候,有几件事情需要明确指定:
- 设置 Pod 的数量;
- 贴上标签,比如 env=development;
- 设置环境变量,比如 SIMPLE_SERVICE_VERSION;
kubectl create -f fan.yaml
kubectl get deploy
kubectl get replicaset
kubectl get pods
!!!如果要删除副本集和监管的 Pod,那么需要删除部署,即 kubectl delete deployment/fancyapp。不要单独删除 Pod,因为删除 Pod 会重建;
部署允许用户伸缩应用的规模,也可以升级和回滚到前一个版本。一般来说,对于需要多个具有相同特征的 pod 的无状态应用来说,这些方法非常实用;
!!!通常「部署」负责监管「Pod」和「副本集」,允许你细致地控制如何以及何时应该将该 Pod 升级到最新的版本,或者回滚到之前的版本。在某些特殊情况下爱,比如需要调试某个 Pod,可以在部署的不同版本之间切换!!!
!!!「副本集」将取代「副本控制器」,二者的区别是「副本集」支持以集合为基础的标签与查询,但是以后「副本集」可能会有更多的新功能加入,将淘汰「副本控制器」!!!
可以使用 kubectl create 命令及–dry-run 选项生成清单文件。可以先生成 YAML 或 JOSN 格式的清单文件,方便以后使用:
关于「部署」可以参考「Deployments」手册;
4.5. Updating a Deployment
如何将「部署」更新到新版本的程序?
只需要更新部署:
# kubectl set image deployment sise –image=afdae/simvsaf:0.4.0
# kubectl rollout history deployment sise
如果想修改部署,可以使用kubectl edit deployment sise,该命令会在编辑器中打开部署文件,退出编辑器后自动更新部署。使用 KUBE_EDITOR 环境变量指定的编辑器;
使用kubectl rollout history deployment sise查看;
可以使用kubectl create的--record选项指定 CHANGE-CAUSE 列。如果向了解什么变更触发了新版本,则可以加上此选项;
还有一些其他可以更新部署的命令:
# kubectl replace -f bar.yaml # 替换部署,但替换的部署对象必须存在;
# kubectl patch demployment sise -p ‘{“spec”:{“template”:{“spec”:{“containers”:[{“name”:”sise”, “image”:”simpadfas:0.5.0″}]}}}}’
另外可以撤回操作:kubetl rollout undo deployment sise ??to?revision=2
然后使用kubectl get deployment/sise -o yaml确认回退成功;
只有 POD 模板(在.spec.template 下的键值)的变更才会触发新的部署,例如环境变量、端口号、容易映像等等。部署方面的变更,比如副本个数,不会触发新的部署;
参考文献
一个简单的 Kubernetes 应用部署示例
Kubernetes 中的 nodePort,targetPort,port 的区别和意义(转)
Kubernetes how to make Deployment to update image
Basic usage – NGINX Ingress Controller