k8s启动容器,一定要理解 namespace 、deployment 、 pod 、container 、service 、labels 之间的关系,大体关系是这样的。
namespace 就好比是一个大的分组,一个k8s集群内可以创建多个namespace ,在它之下才能创建deployment ,然后在 deployment 之下可以启动多个名字一样的 pod(名字一样,id不同,pod全名是pod名加id组成的) ,在一个pod内可以启动多个 container ,一般情况下,一个pod内只跑一个容器,有些特殊的场景才会在pod内启动多个容器;创建了 service 可以将 pod 对 k8s 集群内进行dns解析,并且提供负载均衡能力,同一个namespace下的service可以直接使用 service名字进行解析,不同namespace执行的 service 需要加上 servicename.namespace 才能解析,并且,要解析service的话,只能在pod的容器内进行,容器之外无法解析。
最危险的操作是删除namespace,删除了这个的话,它下面的所有东西全部将被删除,所以namespace 、service 、pod 的yaml文件一定要分类放好,三者各自放在自己的目录中。
k8s各namespace之下的 pod 的 ip 在集群内可以直接通信。
进入正题
以下是namespace的 yaml 文件
kind 指定文件类型为 Namespace
metadata 下定义 Namespace 名字为 product ,给这个 Namespace 定义一个 labels 为 name=product
cat >> product_namespaces.yaml << EOF
apiVersion: v1
kind: Namespace
metadata:
name: product
labels:
name: product
EOF
启动Namespace并查看
kubectl create -f product_namespaces.yaml
kubectl get namespaces
以下是我在生产环境的 pod 的yaml 文件,差不多已经很完善了。经过了一年多的不断完善。
创建 Deployment / pod 的 yaml 配置文件
cat >> app_aas.yaml << EOF
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: aas
namespace: product
labels:
app: aas
spec:
selector:
matchLabels:
app: aas
revisionHistoryLimit: 5
replicas: 2
minReadySeconds: 60
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
template:
metadata:
labels:
app: aas
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- aas
topologyKey: kubernetes.io/hostname
terminationGracePeriodSeconds: 60
imagePullSecrets:
- name: resecret-product
nodeSelector:
apptype: memnode
containers:
- name: aas
readinessProbe:
httpGet:
path: /aas/
port: 8080
scheme: HTTP
initialDelaySeconds: 80
timeoutSeconds: 20
livenessProbe:
httpGet:
path: /aas/
port: 8080
scheme: HTTP
initialDelaySeconds: 80
timeoutSeconds: 20
env:
- name: JAVA_OPTS
value: "-Xms1024M -Xmx1024M -server -Duser.timezone=GMT+08"
image: registry.test.com/appimage/aas:AAS.01.00.001.release
resources:
limits:
cpu: "600m"
memory: 2048Mi
requests:
cpu: "300m"
memory: 1280Mi
volumeMounts:
- mountPath: /etc/localtime
readOnly: false
name: localtime
- mountPath: /home/gooagoo/config
readOnly: false
name: appconfig
- mountPath: /home/gooagoo/resource
readOnly: false
name: appresource
- mountPath: /home/gooagoo/log
readOnly: false
name: log
- mountPath: /opt/tomcat/logs
readOnly: false
name: tomcatlog
- mountPath: /mnt/mfs
readOnly: false
name: mnt
volumes:
- name: "localtime"
hostPath:
path: "/etc/localtime"
type: File
- name: "tomcatlog"
hostPath:
path: "/home/app/log/aas/tomcatlogs"
- name: "log"
hostPath:
path: "/home/app/log/aas"
- name: "appconfig"
hostPath:
path: "/home/app/config"
- name: "appresource"
hostPath:
path: "/home/app/resource"
- name: "mnt"
flexVolume:
driver: "alicloud/nas"
options:
server: "15123496df-bee90.cn-beijing.nas.aliyuncs.com"
path: "/"
vers: "4.0"
EOF
创建deployment 和 pod
查看deploy
查看pod
kubectl create -f app_aas.yaml
kubectl get deploy -n product
kubectl get pod -n product
详解:
api版本
apiVersion: extensions/v1beta1
类型为Deployment文件
kind: Deployment
定义Deployment名称、所属namespace、Deployment 的 labels名称
metadata:
name: aas
namespace: product
labels:
app: aas
最外层的spec下的内容定义了pod启动、更新的规则
定义 pod 启动在 labels 为 aas 的 Deployment 内
spec:
selector:
matchLabels:
app: aas
指定可以列出pod的历史版本个数为 5 个、pod副本为2个、滚动更新间隔为60s 、每次最多更新1个
revisionHistoryLimit: 5
replicas: 2
minReadySeconds: 60
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
定义pod的 labels 名称为 aas
template:
metadata:
labels:
app: aas
第二层spec内定义pod的详细启动参数
防止带有相同 labels 的pod 不能启动到一个节点,避免相同应用启动到同一个节点,节点挂掉后,应用不能提供服务,生成环境建议必须要加这个。terminationGracePeriodSeconds官方解释为优雅的关闭pod,我的理解是就好比是 kill 命令不带 -9 ,最大限时为 60s ,超过时间后则强制杀掉 pod。
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- aas
topologyKey: kubernetes.io/hostname
terminationGracePeriodSeconds: 60
启动pod所使用的镜像时私有docker仓库的话,使用自建的 Secrets 名称为 resecret-product 的授权拉取站点镜像,如何创建 secrets ,请参考文档: k8s创建secret,拉取私有仓库的镜像;并且pod只能分配到 labels 的键值为 apptype=memnode 的节点上,如何创建节点的 labels ,请参考文档:kubernetes调度pod到指定节点
imagePullSecrets:
- name: resecret-product
nodeSelector:
apptype: memnode
指定容器的基础名称为 aas(启动pod后,容器的名称会在指定的 aas 后拼接上随机字符串做为pod实现名称)
readinessProbe:pod创建后,第一次执行探测是需要等待80s,探测超时时间为20s,如果80s后探测健康接口超时时间超过20s,那么pod内的容器应用程序将重启。以下定义的探测接口是 http 请求,整体接口是这样的: http://容器ip:8080/aas/ ,如果在 20s内返回 200 状态码,认为pod启动成功。
livenessProbe: 每隔 80s 探测一次容器内的这个 http 健康接口,如果在 20s内返回 200 状态码,认为pod可以正常工作,否则pod内的容器程序将重启。
containers:
- name: aas
readinessProbe:
httpGet:
path: /aas/
port: 8080
scheme: HTTP
initialDelaySeconds: 80
timeoutSeconds: 20
livenessProbe:
httpGet:
path: /aas/
port: 8080
scheme: HTTP
initialDelaySeconds: 80
timeoutSeconds: 20
env:启动容器时,向容器内传入环境变量名称为JAVA_OPTS,变量值为-Xms1024M -Xmx1024M -server -Duser.timezone=GMT+08 ,如果你打镜像时就定义了环境变量,那么这个会覆盖掉原来的环境变量
image:使用镜像 registry.test.com/appimage/aas:AAS.01.00.001.release 启动
env:
- name: JAVA_OPTS
value: "-Xms1024M -Xmx1024M -server -Duser.timezone=GMT+08"
image: registry.test.com/appimage/aas:AAS.01.00.001.release
requests:pod启动时,直接给容器中的系统分配 300m 的cpu (容器内使用的cpu是宿主机的逻辑核数,每核cpu使用一点cpu,加起来一共只能使用300m,1000m为1核),1024m的内存。
limits: pod启动后,最多可以消耗300m的cpu,最多可以消耗宿主机1280m内存。
resources:
limits:
cpu: "300m"
memory: 1280Mi
requests:
cpu: "300m"
memory: 1024Mi
volumeMounts:指定将要挂载到容器内的文件或者目录的路径,readOnly为true时,挂载到容器内的文件或目录为只读权限
volumes:挂载到容器内的路径在宿主机对应的路径
flexVolume : 挂载阿里云 nas 的方式,挂载nas,需要在宿主机安装 nfs 客户端才行。
volumeMounts:
- mountPath: /etc/localtime
readOnly: false
name: localtime
- mountPath: /home/gooagoo/config
readOnly: false
name: appconfig
- mountPath: /home/gooagoo/resource
readOnly: false
name: appresource
- mountPath: /home/gooagoo/log
readOnly: false
name: log
- mountPath: /opt/tomcat/logs
readOnly: false
name: tomcatlog
- mountPath: /mnt/mfs
readOnly: false
name: mnt
volumes:
- name: "localtime"
hostPath:
path: "/etc/localtime"
type: File
- name: "tomcatlog"
hostPath:
path: "/home/gooagoo/log/aas/tomcatlogs"
- name: "log"
hostPath:
path: "/home/gooagoo/log/aas"
- name: "appconfig"
hostPath:
path: "/home/gooagoo/config"
- name: "appresource"
hostPath:
path: "/home/gooagoo/resource"
- name: "mnt"
flexVolume:
driver: "alicloud/nas"
options:
server: "23fd346df-fds10.cn-beijing.nas.aliyuncs.com"
path: "/"
vers: "4.0"
以下是启动service使用的配置文件
文件详解:
kind 指定文件为 Service
metadata指定service名字为 aas ,在 product 的 namespace 中创建
spec下的内容为开放 service 的 8080 端口(pod内容器对外的什么端口,这里就用什么端口,它将直接映射在pod中),并且代理labels是 app=aas 的 pod
如上所说,要使用service名字 aas 找到 pod ,只能在 启动 pod 的容器中才能解析出来。
cat >> aas_service.yaml << EOF
apiVersion: v1
kind: Service
metadata:
name: aas
namespace: product
spec:
ports:
- port: 8080
selector:
app: aas
EOF
创建service 和查看 servic
kubectl create -f aas_service.yaml
kubectl get svc -n product
如果pod或者service已经创建,修改了yaml文件后,需要重读 yaml 文件的话,可以用下面的命令
kubectl apply -f app_aas.yaml
kubectl apply -f aas_service.yaml
使用 app_aas.yaml 文件删除 deploy 和 pod(删除service、namespace同理,但是删除namespace的话,下面的所有东西都会被删除,所以namespace创建后,一般就不会再动了)
kubectl delete -f app_aas.yaml
如果删除了yaml文件的话,要删除pod的话,有两种方式,直接删除pod会自动再创建,需要删除deploy后,pod 才不会自动再创建
删除pod,自动创建,可以把这个功能当做重新分配pod到k8s工作节点(一定要指定命名空间,即namespace)
kubectl delete po aas-6a5s2gf43dg34 -n product
不使用 yaml 文件永久删除的话,请直接删除deploy
kubectl delete deploy aas -n product
不使用 yaml 文件永久删除service
kubectl delete -f svc aas -n product