一. Kubernetes入门
1.1 Kubernetes创建POD过程
1.2. Kubernetes基本操作
命令 | 说明 | 用法 |
create | 创建 | kubectl create -f xx.yaml |
edit | 编辑 | kubectl edit svc [POD的service名称] |
get | 获取 | kubectl get pod --namespace=XXX |
patch | 更新 | kubectl patch -f xx.yaml |
delete | 删除 | kubectl delete pod --namespcae=XXX [POD名称] |
expose | 暴露端口 | kubectl expose deployment nginx --port=8912 --target-port=80 --type=NodePort |
run | 运行/创建 | kubectl run my-nginx --image=nginx:1.17.3 |
describe | 描述 | kubectl describe pod pod名 -n 命名空间名 |
logs | 日志 | kubectl logs -f Pod名称 -n 命名空间名 |
exec | 执行 | kubectl exec -it pod名 -n 命名空间 – /bin/bash |
rollout | 回滚 | kubectl rollout history deployment 应用部署名称; kubectl rollout undo deployment 应用部署名称 --to-revision=1 |
scale | 扩容/缩容 | kubectl scale --replicas=数量 deployment 部署名称 |
apply | 应用 | kubectl apply-f xx.yaml |
1.2.1.namespace
Namespace是对一组资源和对象的抽象集合,比如可以用来将系统内部的对象划分为不同的项目组或用户组。常见的pods, services, replication controllers和deployments等都是属于某一个namespace的(默认是default),而node, persistentVolumes等则不属于任何namespace。
Namespace常用来隔离不同的用户,比如Kubernetes自带的服务一般运行在kube-system namespace中。
命令行直接创建
$ kubectl create namespace dev
文件创建
apiVersion: v1
kind: Namespace
metadata:
name: dev
1.2.2. pod
Pod是 Kubernetes 集群上的最基本的单元,同一个Pod中的应用可以共享磁盘,Pod 是一组容器(可包含一个或多个应用程序容器.
apiVersion: v1
kind: Pod
metadata:
name: redis
namespace: dev
spec:
containers:
- name: redis
image: redis
volumeMounts:
- name: redis-storage
mountPath: /data/redis
volumes:
- name: redis-storage
emptyDir: {}
1.2.3 deployment
Deployment为Pod和ReplicaSet提供了一个声明式定义方法,用来替代以前的ReplicationController来方便的管理应用。可以通过定义Deployment来创建Pod和ReplicaSet滚动升级和回滚应用、扩容和缩容、暂停和继续Deployment。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
namespace: dev
spec:
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
1.2.4 service
Pod 是应用程序的载体,我们可以通过 Pod 的 IP 来访问应用程序,但是 Pod 的 IP 地址不是固定的,不方便直接采用 Pod 的 IP 对服务进行访问。 Service 会对提供同一个服务的多个 Pod 进行聚合,并且提供一个统一的入口地址,通过访问 Service 的入口地址就能访问到后面的 Pod 服务。
apiVersion: v1 # 版本
kind: Service # 类型
metadata: # 元数据
name: nginx_svc# 资源名称
namespace: dev# 命名空间
spec:
selector: # 标签选择器,用于确定当前Service代理那些Pod
app: nginx
type: NodePort # Service的类型,指定Service的访问方式
clusterIP: 80# 虚拟服务的IP地址
sessionAffinity: # session亲和性,支持ClientIP、None两个选项,默认值为None
ports: # 端口信息
- port:80 # Service端口
protocol: TCP # 协议
targetPort : 80 # Pod端口
nodePort: 30001# 主机端口
1.2.5 configMap
ConfigMap用于保存配置数据的键值对,可以用来保存单个属性,也可以用来保存配置文件。
apiVersion: v1
kind: ConfigMap
metadata:
name: cm
namespace: dev
data:
# 类属性键;每一个键都映射到一个简单的值
how: very
type: charm
# 类文件键
config.yml: |
enemy.types=aliens,monsters
player.maximum-lives=5
---apiVersion: v1
kind: Pod
metadata:
name: test-pod
namespace: dev
spec:
containers:
- name: test-container
image: gcr.io/google_containers/busybox
command: [ "/bin/sh", "-c", "env" ]
env:
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
name: cm
key: how
- name: SPECIAL_TYPE_KEY
valueFrom:
configMapKeyRef:
name: cm
key: type
volumeMounts:
- name: cm
mountPath: /data/#容器挂在路径
volumes:
- name: cm
configMap:
name: cm #将config.yml文件挂在容器的/data/目录下
restartPolicy: Never
1.2.6 pv和pvc
PV(Persistent Volume)是持久化卷的意思,是对底层的共享存储的一种抽象。一般情况下 PV 由 Kubernetes 管理员进行创建和配置,它和底层具体的共享存储技术有关,并通过插件完成和共享存储的对接。
PVC(Persistent Volume Claim)是持久化卷声明的意思,是用户对于存储需求的一种声明。换言之,PVC 其实就是用户向Kubernetes 系统发出的一种资源需求申请。
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv_test
labels:
pv: pv_test
spec:
storageClassName: pv_test # 用于分组
capacity:
storage: 20m
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Retain #手动回收
nfs: # 使用 nfs 存储驱动
path: /data # nfs 共享的目录,mkdir -pv /nfs/data/20m
server: 192.168.70.129 # nfs 服务端的 IP 地址或 hostname
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc_test
namespace: dev
labels:
app: pvc_test
spec:
storageClassName: pv_test
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 500m
selector:
matchLabels:
pv: pv_test
---
apiVersion: v1
kind: Pod
metadata:
name: nginx
namespace: dev
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.17.3
resources:
limits:
cpu: 200m
memory: 500Mi
requests:
cpu: 100m
memory: 200Mi
ports:
- containerPort: 80
name: http
volumeMounts:
- name: localtime
mountPath: /etc/localtime
- name: html
mountPath: /usr/share/nginx/html/
volumes:
- name: localtime
hostPath:
path: /usr/share/zoneinfo/Asia/Shanghai
- name: html
persistentVolumeClaim:
claimName: pvc_test
readOnly: false
restartPolicy: Always
PV 的生命周期
○ Available(可用):表示可用状态,还未被任何 PVC 绑定。
○ Bound(已绑定):表示 PV 已经被 PVC 绑定。
○ Released(已释放):表示 PVC 被删除,但是资源还没有被集群重新释放。
○ Failed(失败):表示该 PV 的自动回收失败。
PV 的访问模式:用来描述用户应用对存储资源的访问权限
○ ReadWriteOnce(RWO):读写权限,但是只能被单个节点挂载。
○ ReadOnlyMany(ROX):只读权限,可以被多个节点挂载。
○ ReadWriteMany(RWX):读写权限,可以被多个节点挂载。
1.2.7 ingress
通常情况下,service和pod仅可在集群内部网络中通过IP地址访问。所有到达边界路由器的流量或被丢弃或被转发到其他地方。Service 可以使用 NodePort 暴露集群外访问端口,但是性能低、不安全并且端口的范围有限。Service 缺少七层(OSI 网络模型)的统一访问入口,负载均衡能力很低,不能做限流、验证非法用户、链路追踪等等。Ingress 公开了从集群外部到集群内 服务 的 HTTP 和 HTTPS 路由。流量路由由 Ingress 资源上定义的规则控制。 使用 Ingress 作为整个集群统一的入口,配置 Ingress 规则转发到对应的 Service 。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
kubernetes.io/ingress.rule-mix: "true"
nginx.ingress.kubernetes.io/proxy-body-size: 50m
nginx.ingress.kubernetes.io/use-regex: "true"
name: test_ing
namespace: dev
spec:
tls:
- hosts:
- test.ingress.com
secretName: test.ingress.com
rules:
- host: test.ingress.com # 指定的监听的主机域名,相当于 nginx.conf 的 server { xxx }
http:# 指定路由规则
paths:
- path: /api # 匹配规则,Prefix 前缀匹配 it.nginx.com/* 都可以匹配到
backend: # 指定路由的后台服务的 service 名称
service:
name: nginx_svc # 服务名
port:
number: 80 # 服务端口
pathType: ImplementationSpecific
status:
loadBalancer:
ingress:
- ip: 192.168.120.1
- ip: 192.168.120.2
二. Kubernetes中文件挂载的四种方式
一个运行中的容器,缺省情况下,对文件系统的写入,都是发生在其分层文件系统的可写层的,一旦容器运行结束,所有写入都会被丢弃。因此需要对持久化支持。Kubernetes 中通过 Volume 的方式提供对存储的支持。
2.1 configMap
ConfigMap 是一种 API 对象,用来将非机密性的数据保存到键值对中。使用时, Pods 可以将其用作环境变量、命令行参数或者存储卷中的配置文件。
ConfigMap 将你的环境配置信息和 容器镜像 解耦,便于应用配置的修改。
在实际工作中许多应用经常会有从配置文件、命令行参数或者环境变量中读取一些配置信息,这些配置信息我们肯定不会直接写死到应用程序中去的,比如你一个应用连接一个redis服务,下一次想更换一个,还得重新去修改代码,重新制作一个镜像,这肯定是不可取的,而ConfigMap 就给我们提供了向容器中注入配置信息的能力,不仅可以用来保存单个属性,也可以用来保存整个配置文件,比如我们可以用来配置一个redis服务的访问地址,也可以用来保存整个redis 的配置文件。
- 将想要挂载的文件内容在tpl中进行define (helm chart),然后载入到configmap.yaml文件中
- 使用卷使用configmap,挂载的方式得到要执行的文件内容
格式为:
spec:containers:- name: image: volumeMounts:- name: nova-confmountPath: /etc/nova/nova.confsubPath: nova.confvolumes:- name: nova-confconfigMap:name: {{ tuple . "nova" |include "nova-name" }}-configmap
注意
1、mountPath会覆盖掉挂载路径下的所有文件,即删除所有文件,只保留挂载的文件
2、subpath只使用在configMap情况下,添加subpath时,表示不会覆盖掉原本的路径下的文件,subpath的值必须是configMap中data下的key值。
具体使用详解
举个栗子[通过文件挂载使用configMap]
这里主要是记录利用yaml来创建configMap,并将配置以配置文件的方式挂载到容器中。
configMap创建和使用的方式有很多种,但本文主要介绍以上的方式,是因为在平时的投产和运维过程中,这个方法用的最为频繁。
现在,在configmap文件中存在这么一段配置:
apiVersion: v1 kind: ConfigMap metadata:name: redis-config data:data.1: hello #以键值对的方式进行存储data.2: world #以键值对的方式进行存储redis.properties6666: | #以文件的形式进行存储,可以在下方直接写配置文件的内容redis.host=127.0.0.1redis.port=6379redis.password=123456
redis.properties6666 是映射到 容器的文件名字 /etc/config/redis.properties6666
/etc/config/下还有两个文件,data.1和data.2
| 竖线文本保留格式
apiVersion: v1 kind: Pod metadata:name: mypod2 spec:containers:- name: busyboximage: busyboxcommand: [ "/bin/sh","-c","cat /etc/config/redis.properties;sleep 1d" ]volumeMounts: #卷挂载- name: config-volume #挂载卷的名称mountPath: /etc/config #挂载到容器中的位置volumes: #创建卷- name: config-volume #创建的卷名称configMap: #从configMap中挂载name: redis-config #挂载configMap中redis-configrestartPolicy: Never
如果我们不想挂载configMap中的所有配置,可以使用items。使用items,还可以给文件重新命名,而不以默认的key作为文件名。
volumes:- name: configconfigMap:name: configmapitems:- key: data.1 # 原文件名(key的名称)path: userinfo # 修改之后的文件名(key的名称)- key: data.2path: userinfo2
2.2 hostPath
- 将node节点(主机)的本地文件挂载到容器中,比如实现本地时间的同步功能
- 这种卷一般和DaemonSet搭配使用,用来操作主机文件,例如进行日志采集的 FLK 中的 FluentD 就采用这种方式,加载主机的容器日志目录,达到收集本主机所有日志的目的。
spec:containers:- name: httpd-deploymentimagePullPolicy: IfNotPresentimage: nginx:1.1.1volumeMounts:- name: host-rootmountPath: /etc/nova/nova.confsubPath: nova.confvolumes:- name: host-roothostPath:path: /type: Directory
注意
1、hostPath不用subPath这一项,直接就是选择挂载的路径;不会覆盖原有文件夹下的文件
2、不提供pod的亲和性,即host path映射的目录在node1,而pod可能被调度到node2,导致原来的在node1的数据不存在,pod一直无法启动起来;
3、能够提供pv/pvc/storage class的方式使用;
4、数据能持久化。
2.3 gitRepo
- 可以挂载git性质的文件或者目录
apiVersion: v1
kind: Pod
metadata:name: gitrepo-volume-pod
spec:containers:- image: nginx:alpinename: web-servervolumeMounts:- name: htmlmountPath: /usr/share/nginx/htmlreadOnly: trueports:- containerPort: 80protocol: TCPvolumes:- name: htmlgitRepo:repository: https://github.com/luksa/kubia-website-example.gitrevision: masterdirectory: .
2.4 emptyDir
- 顾名思义,EmptyDir是一个空目录,他的生命周期和所属的 Pod 是完全一致的,可能读者会奇怪,那还要他做什么?EmptyDir的用处是,可以在同一 Pod 内的不同容器之间共享工作过程中产生的文件(类似于共享内存,但这里默认是共享吃磁盘空间的,看下面2)。
- 缺省情况下,EmptyDir 是使用主机磁盘进行存储的(共享磁盘空间),也可以设置emptyDir.medium 字段的值为Memory,来提高运行速度(共享内存的方式),但是这种设置,对该卷的占用会消耗容器的内存份额。
apiVersion: v1
kind: Pod
metadata:name: test-pod
spec:containers:- image: busyboxname: test-emptydircommand: [ "sleep", "3600" ]volumeMounts:- mountPath: /dataname: data-volumevolumes:- name: data-volumeemptyDir: {}
注意:
1.需要使用内存作为emptyDir的可用存储资源也是可以的,只需要在创建emptyDir卷时增加一个emptyDir.medium字段的定义,并赋值为"Memory"即可;
2.在使用tmpfs文件系统作为emptyDir的存储后端时,如果遇到node节点重启,则emptyDir中的数据也会全部丢失。同时,你编写的任何文件也都将计入Container的内存使用限制,即empty dir方式保存的数据不能持久化。
2.5 挂载到 nfs
Kubernetes中使用NFS