kubernetes
1. 导读
know
k8s
的优点- 高可用,不宕机,自动灾难恢复
- 灰度更新,不影响业务正常运转 不会一次清除所有的
- 一键回滚到历史版本
- 方便的伸缩扩展(应用伸缩,机器加减)、提供负载均衡
- 有一个完善的生态
k8s
master
- 主节点,控制平台,不需要很高性能,不跑任务,通常一个就行了,也可以开多个主节点来提高集群可用度。
worker
- 工作节点,可以是虚拟机或物理计算机,任务都在这里跑,机器性能需要好点;通常都有很多个,可以不断加机器扩大集群;每个工作节点由主节点管理
pod
- 豆荚,
K8S
调度、管理的最小单位,一个Pod
可以包含一个或多个容器,每个Pod
有自己的虚拟IP
。一个工作节点可以有多个pod
,主节点会考量负载自动调度pod
到哪个节点运行。
- 豆荚,
- 工作负载分类
Deployment
适合无状态应用,所有pod
等价,可替代StatefulSet
有状态的应用,适合数据库这种类型。DaemonSet
在每个节点上跑一个Pod
,可以用来做节点监控、节点日志收集等Job & CronJob
Job
用来表达的是一次性的任务,而CronJob
会根据其时间规划反复运行
kubectl
kubectl
是一个用来跟K8S
集群进行交互的命令行工具1
2
3brew install kubectl
# 查看节点。
kubectl get node
1.1 minikube
1.2 云服务器安装
- 可视化操作
- 登录阿里云控制台 产品搜索
Kubernates
- 选择流量计费测试
- 环境默认就配置好了
1.3 裸机安装
- 裸机安装 需要两台机器 自己安装k8s组件
- 主节点
docker
kubectl
kubeadm
集群初始化工具
- 工作节点
docker
kubelet
管理Pod
和容器kube-proxy
网络代理
1.3.1 购买服务器
1 | // 记录自己的公网和内网地址。 下面的这些服务器已经销毁了 只是举例 |
1.3.2 服务器安装启动依赖
1 | # 每个节点分别设置对应主机名 |
1.3.3 修改配置
kubernetes
官方推荐docker
等使用systemd
作为cgroupdriver
,否则kubelet
启动不了1
2
3
4
5
6
7
8
9
10
11# 修改 docker 配置(所有节点)
cat <<EOF > daemon.json
{
"exec-opts": ["native.cgroupdriver=systemd"],
"registry-mirrors": ["https://ud6340vz.mirror.aliyuncs.com"]
}
EOF
mv daemon.json /etc/docker/
# 重启生效
systemctl daemon-reload
systemctl restart docker
1.3.4 主节点初始化集群
用
kubeadm
初始化集群(仅在主节点跑)1
2
3
4
5
6
7
8
9
10
11
12
13
14# 初始化集群控制台 Control plane
# 失败了可以用 kubeadm reset 重置
kubeadm init --image-repository=registry.aliyuncs.com/google_containers
# 记得把 kubeadm join xxx 保存起来
# 忘记了重新获取:kubeadm token create --print-join-command
# 复制授权文件,以便 kubectl 可以有权限访问集群
# 如果你其他节点需要访问集群,需要从主节点复制这个文件过去其他节点
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
# 在其他机器上创建 ~/.kube/config 文件也能通过 kubectl 访问到集群把工作节点加入集群(只在工作节点跑)
1 | # |
- 安装网络插件,否则
node
是NotReady
状态(主节点跑)1
2
3# 很有可能国内网络访问不到这个资源,你可以网上找找国内的源安装
# flannel
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
2. demo
1 | # 运行一个pod 名字是testapp |
- 执行命令
kubectl apply -f app.yaml
pod.yaml
1
2
3
4
5
6
7
8
9apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
# 定义容器,可以多个
containers:
- name: test-k8s # 容器名字
image: ccr.ccs.tencentyun.com/k8s-tutorial/test-k8s:v1 # 镜像
3. kubernetes 常用命令
1 | # 部署应用 |
4.service
service
ClusterIP
默认的,仅在集群内可用NodePort
- 暴露端口到节点,提供了集群外部访问的入口 端口范围固定
30000 ~ 32767
- 暴露端口到节点,提供了集群外部访问的入口 端口范围固定
LoadBalancer
- 需要负载均衡器(通常都需要云服务商提供,裸机可以安装
METALLB
测试) - 会额外生成一个
IP
对外服务k8S
支持的负载均衡器:负载均衡器
- 需要负载均衡器(通常都需要云服务商提供,裸机可以安装
Service
通过label
关联对应的Pod
Servcie
生命周期不跟Pod
绑定,不会因为Pod
重创改变IP
提供了负载均衡功能,自动转发流量到不同
Pod
可对集群外部提供访问端口
集群内部可通过服务名字访问
4.1 yaml
kubectl get svc
查看服务kubectl describe svc test-k8s
查看服务详情1
2
3
4
5
6
7
8
9
10
11
12apiVersion: v1
kind: Service
metadata:
name: test-k8s
spec:
selector:
app: test-k8s
type: ClusterIP
ports:
- port: 8080 # 本 Service 的端口
targetPort: 8080 # 容器端口
#服务的默认类型是
ClusterIP
,只能在集群内部访问,我们可以进入到Pod
里面访问:kubectl exec -it pod-name -- bash
- curl http://test-k8s:8080
集群外部访问,可以通过端口转发实现(只适合临时测试用)
kubectl port-forward service/test-k8s 8888:8080
4.2 对外暴露服务
1 | apiVersion: v1 |
4.3 多端口
- 必须配置
name
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17apiVersion: v1
kind: Service
metadata:
name: test-k8s
spec:
selector:
app: test-k8s
type: NodePort
ports:
- port: 8080 # 本 Service 的端口
name: test-k8s # 必须配置
targetPort: 8080 # 容器端口
nodePort: 31000 # 节点端口,范围固定 30000 ~ 32767
- port: 8090
name: test-other
targetPort: 8090
nodePort: 32000
5. Deployment
Deployment
通过label
关联起来Pods
5.1 yaml
1 | apiVersion: apps/v1 |
5.2 pod报错
1 | # 如果你运行 kubectl describe pod/pod-name 发现 Events 中有下面这个错误 |
5.3 将Pod指定到某个节点运行
- 将 Pod 分配给节点
- 计算资源配额
1
2
3
4
5
6
7
8
9
10
11
12
13apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
nodeSelector:
disktype: ssd
6. StatefulSet
6.1 MongoDB
1 | apiVersion: apps/v1 |
6.2 hostPath
1 | apiVersion: apps/v1 |
6.3 Storage Class (SC)
- 将存储卷划分为不同的种类,例如:SSD,普通磁盘,本地磁盘,按需使用。
1
2
3
4
5
6
7
8
9apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: slow
provisioner: kubernetes.io/aws-ebs
parameters:
type: io1
iopsPerGB: "10"
fsType: ext4
6.4 Persistent Volume (PV)
- 描述卷的具体信息,例如磁盘大小,访问模式。文档,类型
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23apiVersion: v1
kind: PersistentVolume
metadata:
name: mongodata
spec:
capacity:
storage: 2Gi
volumeMode: Filesystem # Filesystem(文件系统) Block(块)
accessModes:
- ReadWriteOnce # 卷可以被一个节点以读写方式挂载
persistentVolumeReclaimPolicy: Delete
storageClassName: local-storage
local:
path: /root/data
nodeAffinity:
required:
# 通过 hostname 限定在某个节点创建存储卷
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- node2
6.5 Persistent Volume Claim (PVC)
- 对存储需求的一个申明,可以理解为一个申请单,系统根据这个申请单去找一个合适的
PV
- 还可以根据
PVC
自动创建PV
。1
2
3
4
5
6
7
8
9
10apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mongodata
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: "local-storage"
resources:
requests:
storage: 2Gi
6.6 动态卷
1 | apiVersion: apps/v1 |
7. ConfigMap & Secret
7.1 ConfigMap
ConfigMap
,可以方便的配置一些变量- 数据库密码 链接地址 …
1
2
3
4
5
6
7
8
9
10
11apiVersion: v1
kind: ConfigMap
metadata:
name: mongo-config
data:
mongoHost: mongodb-0.mongodb
#
# 应用
kubectl apply -f configmap.yaml
# 查看
kubectl get configmap mongo-config -o yaml
- 数据库密码 链接地址 …
7.2 Secret
- 一些重要数据,例如密码、
TOKEN
,我们可以放到secret
中 - 注意,数据要进行
Base64
编码1
2
3
4
5
6
7
8
9
10
11
12
13
14apiVersion: v1
kind: Secret
metadata:
name: mongo-secret
# Opaque 用户定义的任意数据,更多类型介绍 https://kubernetes.io/zh/docs/concepts/configuration/secret/#secret-types
type: Opaque
data:
# 数据要 base64。https://tools.fun/base64.html
mongo-username: bW9uZ291c2Vy
mongo-password: bW9uZ29wYXNz
# 应用
kubectl apply -f secret.yaml
# 查看
kubectl get secret mongo-secret -o yaml - 使用方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mongodb
spec:
replicas: 3
selector:
matchLabels:
app: mongodb
template:
metadata:
labels:
app: mongodb
spec:
containers:
- name: mongo
image: mongo:4.4
# IfNotPresent 仅本地没有镜像时才远程拉,Always 永远都是从远程拉,Never 永远只用本地镜像,本地没有则报错
imagePullPolicy: IfNotPresent
env:
- name: MONGO_INITDB_ROOT_USERNAME
valueFrom:
secretKeyRef:
name: mongo-secret
key: mongo-username
- name: MONGO_INITDB_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mongo-secret
key: mongo-password
# Secret 的所有数据定义为容器的环境变量,Secret 中的键名称为 Pod 中的环境变量名称
# envFrom:
# - secretRef:
# name: mongo-secret
7.3 挂载为文件
- 更适合证书文件
- 挂载后,会在容器中对应路径生成文件,一个 key 一个文件,内容就是 value
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: mypod
image: redis
volumeMounts:
- name: foo
mountPath: "/etc/foo"
readOnly: true
volumes:
- name: foo
secret:
secretName: mysecret
8. Helm & 命名空间
Helm
类似npm,pip,docker hub
, 可以理解为是一个软件库,可以方便快速的为我们的集群安装一些第三方软件。- 使用
Helm
我们可以非常方便的就搭建出来MongoDB / MySQL
副本集群,YAML
文件别人都给我们写好了,直接使用
8.1 安装
1 | curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash |
8.2 安装MongoDB
1 | # 安装 |
8.3 命名空间
1 | # 创建命名空间 |
9. Ingress
ngress
为外部访问集群提供了一个 统一 入口,避免了对外暴露集群端口;- 功能类似
Nginx
,可以根据域名、路径把请求转发到不同的Service
。 - 可以配置
https
- 功能类似
- 跟
LoadBalancer
有什么区别?LoadBalancer
需要对外暴露端口,不安全;- 无法根据域名、路径转发流量到不同
Service
,多个Service
则需要开多个LoadBalancer;
- 功能单一,无法配置
https
- 云服务会自动配置 可视化配置
1 | apiVersion: networking.k8s.io/v1 |
10. 链接
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 LiuYuanhua!
评论