kubeadm部署k8s集群
环境准备
主机 | IP | 配置 | 软件 |
---|---|---|---|
k8s-adm-master | 10.0.0.15 | 2核2G | docker-ce,kubelet,kubeadm,kubectl |
k8s-adm-node1 | 10.0.0.16 | 2核2G | docker-ce,kubelet,kubeadm,kubectl |
-
关闭:
selinux
,firewalld
和NetworkManager
,postfix
(非必须) -
修改IP地址、主机名
hostnamectl set-hostname 主机名
sed -i 's/200/IP/g' /etc/sysconfig/network-scripts/ifcfg-eth0
- 添加hosts解析
cat > /etc/hosts <<EOF
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
10.0.0.15 k8s-adm-master
10.0.0.16 k8s-adm-node1
EOF
- 修改内核参数,关闭swap分区
cat <<EOF > /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sysctl --system
swapoff -a
sed -i 's%/dev/mapper/centos-swap%#&%g' /etc/fstab
安装docker-ce
wget -O /etc/yum.repos.d/docker-ce.repo https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/docker-ce.repo
yum install docker-ce-18.09.7 -y
systemctl enable docker.service
systemctl start docker.service
systemctl start docker
cat > /etc/docker/daemon.json <<EOF
{
"registry-mirrors": ["https://registry.docker-cn.com"],
}
EOF
systemctl restart docker.service
docker info
安装kubeadm
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
yum install kubelet-1.15.4-0 kubeadm-1.15.4-0 kubectl-1.15.4-0 -y
systemctl enable kubelet.service
systemctl start kubelet.service
使用kubeadm初始化k8s集群
- 选择一个控制节点(k8s-adm-master),初始化一个k8s集群:
kubeadm init --kubernetes-version=v1.15.4 --image-repository registry.aliyuncs.com/google_containers --pod-network-cidr=10.244.0.0/16 --service-cidr=10.254.0.0/16
- 等待镜像下载,可以使用
docker images
查看下载进度。 - Your Kubernetes control-plane has initialized successfully!
- 执行提示命令1:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
- 执行提示命令2:node节点加入k8s集群
kubeadm join 10.0.0.15:6443 --token uwelrl.g25p8ye1q9m2sfk7
--discovery-token-ca-cert-hash sha256:e598a2895a53fded82d808caf9b9fd65a04ff59a5b773696d8ceb799cac93c5e
默认 token 24H过期,需要重新生成
kubeadm token create --print-join-command
默认 证书 10年过期,查看
cfssl-certinfo -cert /etc/kubernetes/pki/ca.crt
- kubectl命令行TAB键补全:
echo "source <(kubectl completion bash)" >> ~/.bashrc
master节点配置flannel网络
- 准备yaml文件
cat <<EOF >> /etc/hosts
199.232.4.133 raw.githubusercontent.com
EOF
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
- 创建资源
kubectl create -f kube-flannel.yml
- 查看资源
kubectl get all -n kube-system
kubectl get nodes
metric-server
-
准备yaml文件,使用国内镜像地址(2个),修改一些其他参数
-
创建资源(准备镜像:registry.aliyuncs.com/google_containers/addon-resizer:1.8.5和registry.aliyuncs.com/google_containers/metrics-server-amd64:v0.3.3)
kubectl create -f .
- 查看资源监控
kubectl top nodes
导出所有镜像
docker save `docker images|awk 'NR>1{print $1":"$2}'|xargs -n 50` -o docker_k8s_kubeadm.tar.gz
弹性伸缩
- 创建业务资源
kubectl create -f /root/k8s_yaml/deploy/k8s_deploy2.yaml
- 创建HPA规则
kubectl autoscale deploy nginx --max=6 --min=1 --cpu-percent=5
- 查看pod
kubectl get pod
- 创建service和ingress资源,部署dashboard服务,ab压力测试弹性伸缩。
StatefulSet 资源
StatefulSet (PetSets):宠物应用,有状态的应用,有数据的应用,pod名称固定(有序 01 02 03)。
- 适用于每个Pod中有自己的编号,需要互相访问,以及持久存储区分。
- 例如数据库应用,redis,es集群,mysql集群。
StatefulSet 用来管理 Deployment 和扩展一组 Pod,并且能为这些 Pod 提供序号和唯一性保证。
StatefulSet 为它的每个 Pod 维护了一个固定的 ID。这些 Pod 是基于相同的声明来创建的,但是不能相互替换:无论怎么调度,每个 Pod 都有一个永久不变的 ID。
StatefulSets 对于需要满足以下一个或多个需求的应用程序很有价值:
- 稳定的、唯一的网络标识符。
$(StatefulSet 名称)-$(序号)
- 稳定的、持久的存储。
- 有序的、优雅的部署和缩放。
- 有序的、自动的滚动更新。
使用限制
- 给定 Pod 的存储必须由 PersistentVolume 驱动基于所请求的
storage class
来提供,或者由管理员预先提供。 - 删除或者收缩 StatefulSet 并不会删除它关联的存储卷。保证数据安全。
- StatefulSet 当前需要无头服务(不分配 ClusterIP的 svc 资源)来负责 Pod 的网络标识。需要预先创建此服务。
- 有序和优雅的终止 StatefulSet 中的 Pod ,在删除前将 StatefulSet 缩放为 0。
- 默认 Pod 管理策略(
OrderedReady
) 使用滚动更新,可能进入损坏状态,需要手工修复。
- 搭建NFS提供静态存储
- 配置动态存储
mkdir -p /root/k8s_yaml/sts/ && cd /root/k8s_yaml/sts/
# 实现自动创建PV功能,提供存储类SC
cat > /root/k8s_yaml/sts/nfs-client.yaml <<EOF
kind: Deployment
apiVersion: apps/v1
metadata:
name: nfs-client-provisioner
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app: nfs-client-provisioner
template:
metadata:
labels:
app: nfs-client-provisioner
spec:
serviceAccountName: nfs-client-provisioner
containers:
- name: nfs-client-provisioner
image: quay.io/external_storage/nfs-client-provisioner:latest
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME
value: fuseim.pri/ifs
- name: NFS_SERVER
value: 10.0.0.15
- name: NFS_PATH
value: /data
volumes:
- name: nfs-client-root
nfs:
server: 10.0.0.15
path: /data
EOF
# RBAC
cat > /root/k8s_yaml/sts/nfs-client-rbac.yaml <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-client-provisioner
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: nfs-client-provisioner-runner
rules:
- apiGroups: [""]
resources: ["persistentvolumes"]
verbs: ["get", "list", "watch", "create", "delete"]
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["get", "list", "watch", "update"]
- apiGroups: ["storage.k8s.io"]
resources: ["storageclasses"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["events"]
verbs: ["list", "watch", "create", "update", "patch"]
- apiGroups: [""]
resources: ["endpoints"]
verbs: ["create", "delete", "get", "list", "watch", "patch", "update"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: run-nfs-client-provisioner
subjects:
- kind: ServiceAccount
name: nfs-client-provisioner
namespace: default
roleRef:
kind: ClusterRole
name: nfs-client-provisioner-runner
apiGroup: rbac.authorization.k8s.io
EOF
# 创建SC资源,基于nfs-client-provisioner,设为默认SC
cat > /root/k8s_yaml/sts/nfs-client-class.yaml <<EOF
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: course-nfs-storage
annotations:
storageclass.kubernetes.io/is-default-class: "true"
provisioner: fuseim.pri/ifs
EOF
给sc资源,命令行打默认补丁:
kubectl patch storageclass course-nfs-storage -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
- 创建资源(准备镜像:quay.io/external_storage/nfs-client-provisioner:latest)
kubectl create -f .
- 创建pvc资源yaml文件
cat > /root/k8s_yaml/sts/test_pvc1.yaml <<EOF
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: pvc1
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 10Gi
EOF
- 创建pvc资源:测试动态存储
kubectl create -f test_pvc1.yaml
- 查看资源:验证动态存储
kubectl get pvc
kubectl get pv
- 查看sts解释
kubectl explain sts.spec.volumeClaimTemplates
kubectl explain sts.spec.volumeClaimTemplates.spec
kubectl explain sts.spec.selector.matchLabels
- 创建sts及其依赖svc资源yaml文件
# 创建无头service:不分配 ClusterIP
cat > /root/k8s_yaml/sts/sts_svc.yaml <<EOF
kind: Service
apiVersion: v1
metadata:
name: nginx
spec:
type: ClusterIP
clusterIP: None
ports:
- port: 80
targetPort: 80
selector:
app: nginx
EOF
cat > /root/k8s_yaml/sts/sts.yaml <<EOF
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: nginx
spec:
serviceName: nginx
replicas: 2
selector:
matchLabels:
app: nginx
volumeClaimTemplates:
- metadata:
name: html
spec:
resources:
requests:
storage: 5Gi
accessModes:
- ReadWriteOnce
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.13
volumeMounts:
- name: html
mountPath: /usr/shart/nginx/html
ports:
- containerPort: 80
EOF
- 创建svc和sts资源
kubectl create -f sts_svc.yaml
kubectl create -f sts.yaml
- 查看资源:pod是有序的,对应pvc也是有序的,但pvc无序
kubectl get pod
kubectl get pv
kubectl get pvc
- 直接使用域名访问容器:容器名不变,即域名不变
ping nginx-0.nginx.default.svc.cluster.local
- 查看DNS地址
[root@k8s-adm-master sts]# kubectl get pod -n kube-system -o wide | grep coredns
coredns-bccdc95cf-9sc5f 1/1 Running 2 20h 10.244.0.6 k8s-adm-master <none> <none>
coredns-bccdc95cf-k298p 1/1 Running 2 20h 10.244.0.7 k8s-adm-master <none> <none>
- 解析域名
yum install bind-utils -y
dig @10.244.0.6 nginx-0.nginx.default.svc.cluster.local +short
nginx-0.nginx.default.svc.cluster.local
Pod 的 DNS 子域:
$(主机名).$(所属服务的 DNS 域名)
主机名:
$(StatefulSet 名称)-$(序号)
所属服务的 DNS 域名:
$(服务名称).$(命名空间).svc.$(集群域名)
集群域名:
cluster.local
服务名称由 StatefulSet 的
serviceName
域来设定。
集群域名 服务(名字空间/名字) StatefulSet(名字空间/名字) StatefulSet 域名 Pod DNS Pod 主机名 cluster.local default/nginx default/web nginx.default.svc.cluster.local web-{0..N-1}.nginx.default.svc.cluster.local web-{0..N-1} cluster.local foo/nginx foo/web nginx.foo.svc.cluster.local web-{0..N-1}.nginx.foo.svc.cluster.local web-{0..N-1} kube.local foo/nginx foo/web nginx.foo.svc.kube.local web-{0..N-1}.nginx.foo.svc.kube.local web-{0..N-1}
Job资源
一次性任务,例如:清理es索引。
- 创建job资源yaml文件
mkdir -p /root/k8s_yaml/job/ && cd /root/k8s_yaml/job/
cat > /root/k8s_yaml/job/job.yaml <<EOF
apiVersion: batch/v1
kind: Job
metadata:
name: nginx
spec:
template:
metadata:
name: myjob
spec:
containers:
- name: nginx
image: nginx:1.13
ports:
- containerPort: 80
command: ["sleep","10"]
restartPolicy: Never
EOF
- 创建job资源
kubectl create -f job.yaml
- 查看资源:启动一个pod,10秒后关闭,STATUS:Completed
kubectl get job
kubectl get pod
CronJob资源
定时任务
- 创建cronjob资源yaml文件
cat > /root/k8s_yaml/job/cronjob.yaml <<EOF
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: nginx
spec:
schedule: "*/1 * * * *"
jobTemplate:
spec:
template:
metadata:
name: myjob
spec:
containers:
- name: nginx
image: nginx:1.13
ports:
- containerPort: 80
command: ["sleep","10"]
restartPolicy: Never
EOF
- 创建cronjob资源
kubectl create -f cronjob.yaml
- 查看资源:10秒后创建一个pod
kubectl get cronjobs
kubectl get pod