kubeadm部署kubernetes 1.18集群
Kubeadm 是一个工具,它提供了 kubeadm init
以及 kubeadm join
这两个命令作为快速创建 kubernetes 集群的最佳实践。
kubeadm 通过执行必要的操作来启动和运行一个最小可用的集群。它被故意设计为只关心启动集群,而不是之前的节点准备工作。
kubeadm部署原理
kubeadm 部署k8s集群,主要为以下两步:
# 创建一个 Master 节点
$ kubeadm init
# 将一个 Node 节点加入到当前集群中
$ kubeadm join <Master节点的IP和端口 >
kubeadm init阶段:
自动化的集群机器合规检查;
自动化生成集群运行所需的各类证书及各类配置,并将Master节点信息保存在名为cluster-info的ConfigMap中;
通过static Pod方式,运行API server, controller manager 、scheduler及etcd组件;
生成Token以便其他节点加入集群;
kubeadm join阶段:
节点通过token访问kube-apiserver,获取cluster-info中信息,主要是apiserver的授权信息(节点信任集群);
通过授权信息,kubelet可执行TLS bootstrapping,与apiserver真正建立互信任关系(集群信任节点);
因此kubeadm做的事就是把大部分组件都容器化,通过StaticPod方式运行,并自动化了大部分的集群配置及认证等工作,通过简单几步即可搭建一个可用Kubernetes的集群。
环境准备
IP | 主机名 | 角色 | 操作系统 |
192.168.3.217 | master | master | Centos7 |
192.168.3.218 | node1 | work | Centos7 |
192.168.3.219 | node2 | work | Centos7 |
kubernetes 版本为1.18.2
部署
一、docker环境部署
docker环境需要在3个节点全部安装
1.安装docker ce
# step 1: 安装必要的一些系统工具
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
# Step 2: 添加软件源信息
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# Step 3: 更新并安装 Docker-CE
sudo yum makecache fast
sudo yum -y install docker-ce
# Step 4: 开启Docker服务
sudo service docker start
2.安装阿里云镜像加速器
#针对Docker客户端版本大于 1.10.0 的用户
#通过修改daemon配置文件/etc/docker/daemon.json来使用加速器
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://xxxxxx.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
3.安装docker-compose
curl -L "https://github.com/docker/compose/releases/download/1.25.4/docker-compose-$(uname -s)-$(uname -m)" -o /bin/docker-compose
二、k8s部署
1.系统初始化
kuadm init 阶段,需要进行集群机器的合规检查,请参见Centos7初始化适合k8s运行的系统环境。
通过初始化,即可通过服务器的合规检查。
# 全部节点
192.168.3.217 master
192.168.3.218 node1
192.168.3.219 node2
2.安装kubelet、kubeadm、kubectl
# 所有节点
# 添加阿里kubernetes源
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
# 安装kubelet、kubeadm、kubectl
yum install -y kubelet kubeadm kubectl
systemctl enable kubelet && systemctl start kubelet
其中:
kubeadm:初始化集群;
kubelet:运行在集群中的所有node节点上,负责启动pod和容器;
kubectl:k8s命令行工具,运行在master节点上,通过kubectl可以部署和管理应用,查看各种资源、创建、删除、更新各种组件;
3.初始化集群
初始化集群可以通过yaml配置文件和命令行直接初始化,在此我们都来介绍下。
(1)命令行直接初始化
# master节点
kubeadm init --kubernetes-version=1.18.2 --apiserver-advertise-address=192.168.3.217 --image-repository registry.cn-hangzhou.aliyuncs.com/google_containers --service-cidr=10.1.0.0/16 --pod-network-cidr=10.244.0.0/16
####################################################
Your Kubernetes control-plane has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 192.168.3.217:6443 --token 8nfcuq.joeuirw95y0fi8ga \
--discovery-token-ca-cert-hash sha256:b53601e735acdb21622e6117ea19077b87825c42cd1eaaf30e1df7b83b7b3bd8
其中:
--kubernetes-version 指定kubernetes版本
--apiserver-advertise-address API 服务器所公布的其正在监听的 IP 地址。如果未设置,则使用默认网络接口。
--image-repository 选择用于拉取镜像的容器仓库
--service-cidr service的虚拟 IP 地址,(默认“10.96.0.0/12”)
--pod-network-cidr 指明 pod 网络可以使用的 IP 地址段。如果设置了这个参数,控制平面将会为每一个节点自动分配 CIDRs。
--ignore-preflight-errors 将错误显示为警告的检查列表进行忽略
注意:
由于kubeadm 默认从官网k8s.grc.io下载所需镜像,国内无法访问,需要通过--image-repository指定仓库,在此我们使用"registry.cn-hangzhou.aliyuncs.com/google_containers"。
init打印信息,给了我们下一步的提示,即部署pod网络、将work节点加入集群。
(2)yaml初始化
# master节点
# 1.生成 init 配置文件
kubeadm config print init-defaults > kubeadmin-config.yaml
W0605 14:37:18.548586 7592 configset.go:202] WARNING: kubeadm cannot validate component configs for API groups [kubelet.config.k8s.io kubeproxy.config.k8s.io]
# 2.编辑 yaml 配置文件
vim kubeadmin-config.yaml
apiVersion: kubeadm.k8s.io/v1beta2
bootstrapTokens:
- groups:
- system:bootstrappers:kubeadm:default-node-token
token: abcdef.0123456789abcdef
ttl: 24h0m0s
usages:
- signing
- authentication
kind: InitConfiguration
localAPIEndpoint:
# 需修改当前节点的宿主机地址
advertiseAddress: 192.168.3.217
bindPort: 6443
nodeRegistration:
criSocket: /var/run/dockershim.sock
name: node1
taints:
- effect: NoSchedule
key: node-role.kubernetes.io/master
---
apiServer:
timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta2
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {}
dns:
type: CoreDNS
etcd:
local:
dataDir: /var/lib/etcd
# 镜像仓库
imageRepository: registry.cn-hangzhou.aliyuncs.com/google_containers
kind: ClusterConfiguration
# 版本更改为当前版本
kubernetesVersion: v1.18.2
networking:
dnsDomain: cluster.local
# pod的地址,注意此地址需要和网络插件flannel或其他插件的默认地址保持一致,此处为10.244.0.0
podSubnet: 10.244.0.0/16
# service的地址
serviceSubnet: 10.96.0.0/12
scheduler: {}
# 将调度模式由默认的iptables改为ipvs
---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
featureGates:
SupportIPVSProxyMode: true
mode: ipvs
# 3. 初始化
kubeadm init --config=kubeadm-config.yaml | tee kubeadm-init.log
集群初始化可以按需选择其中一种方式,不过yaml配置文件便于我们日后查看。
注意:
初始化我们使用ipvs调度,如果系统中没有安装ipvs,则会退化为iptables。
4.配置kubectl
kubeadm init 完成初始化后,会打印信息,指示我们如何配置kubectl。
# master节点
echo $HOME
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
5.部署pod网络
如果没有pod网络,那么pod之前无法通信。kubeadm工具安装只支持CNI(Container Network Interface)网络插件,因此需要安装相应插件(例如Flannel、Calico、Romana、Weave-net等插件),我们使用Overlay网络的Flannel插件。
# master节点
kubectl apply -f https://gitlab.abcxlab.com/bootcamp/k8s-quick-start/-/raw/master/k8s/1.0_kube-flannel.yaml
podsecuritypolicy.policy/psp.flannel.unprivileged created
clusterrole.rbac.authorization.k8s.io/flannel created
clusterrolebinding.rbac.authorization.k8s.io/flannel created
serviceaccount/flannel created
configmap/kube-flannel-cfg created
daemonset.apps/kube-flannel-ds-amd64 created
daemonset.apps/kube-flannel-ds-arm64 created
daemonset.apps/kube-flannel-ds-arm created
daemonset.apps/kube-flannel-ds-ppc64le created
daemonset.apps/kube-flannel-ds-s390x created
# 查看状态
kubectl get pod -n kube-system
# flannel 相关pod
kube-flannel-ds-amd64-5gfwh 1/1 Running 1 25d
kube-flannel-ds-amd64-js877 1/1 Running 1 25d
kube-flannel-ds-amd64-pb4d7 1/1 Running 1 25
注意:
k8s的namespace 分为default和kube-system,默认使用default。而k8s的系统组件core-dns、etcd、kube-flannel、kube-proxy、scheduler等都在kube-system中。
如果有多个网卡,可以通过--iface=eth0指定网卡,防止DNS无法解释;
6.加入kuburnetes集群
# work 节点
kubeadm join 192.168.3.217:6443 --token 8nfcuq.joeuirw95y0fi8ga --discovery-token-ca-cert-hash sha256:b53601e735acdb21622e6117ea19077b87825c42cd1eaaf30e1df7b83b7b3bd8
W0522 11:39:24.304798 7867 join.go:346] [preflight] WARNING: JoinControlPane.controlPlane settings will be ignored when control-plane flag is not set.
[preflight] Running pre-flight checks
[preflight] Reading configuration from the cluster...
[preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -oyaml'
[kubelet-start] Downloading configuration for the kubelet from the "kubelet-config-1.18" ConfigMap in the kube-system namespace
[kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml"
[kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env"
[kubelet-start] Starting the kubelet
[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...
This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.
Run 'kubectl get nodes' on the control-plane to see this node join the cluster.
# 查看集群状态
kubectl get nodes
NAME STATUS ROLES AGE VERSION
master Ready master 25d v1.18.2
node1 Ready <none> 25d v1.18.2
node2 Ready <none> 25d v1.18.2
# 组件状态
# 节点信息
kubectl get cs
NAME STATUS MESSAGE ERROR
controller-manager Healthy ok
scheduler Healthy ok
etcd-0 Healthy {"health":"true"}
# 集群信息
kubectl cluster-info
Kubernetes master is running at https://192.168.3.217:6443
KubeDNS is running at https://192.168.3.217:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
Metrics-server is running at https://192.168.3.217:6443/api/v1/namespaces/kube-system/services/https:metrics-server:/proxy
至此,我们的三节点的集群部署就完成了。
实例
k8s部署一个服务的流程大体是:
工作负载(ReplicaSet/Deploymnt/DaemonSet/StatefulSet/Job/CronJob)
不同的工作负载对应不同的服务,如nginx、mysql、计划任务等
Service(Cluster/NodePort/LoadBalance/Ingress)
不同的Service对应不同的服务暴露访问方式,如集群内部访问、对外访问、4层访问还是7层访问。
下面我们将部署一个Nginx服务,并展示Server的服务访问方式。
1.部署Deployment
Nginx是一个无状态服务,因此我们使用Deployment类型的工作负载。
vim nginx-deployment.yaml
# nginx资源清单
apiVersion: apps/v1
kind: Deployment
metadata:
# pod名称
name: nginx-deployment
spec:
# 副本数量
replicas: 3
selector:
matchLabels:
#匹配标签
app: nginx
template:
metadata:
labels:
# 自定义标签,需与上面一致
app: nginx
spec:
containers:
# 镜像名
- name: nginx
# 镜像tag
image: nginx:1.7.9
# 拉取策略,如果本地没有则从远程仓库拉取
imagePullPolicy: IfNotPresent
# master节点执行命令
# 部署
kubectl apply -f nginx-deployment.yaml
#查看pod信息
kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deployment-6dd8bc586b-tgsbj 1/1 Running 0 21h 10.244.1.36 node1 <none> <none>
nginx-deployment-6dd8bc586b-tssbj 1/1 Running 0 21h 10.244.1.37 node1 <none> <none>
nginx-deployment-6dd8bc586b-tgsbj 1/1 Running 0 21h 10.244.2.38 node2 <none> <none>
#访问任意一个pod ip
curl 10.244.1.36
curl 10.244.1.37
curl 10.244.2.36
此时创建完成的pod只能通过pod ip进行访问,但是此pod ip不是固定的,随着pod的创建,pod ip会变化。但是我们可以通过Service提供的访问方式来绑定pod。
2.部署Serveice
vim nginx-service.yaml
apiVersion: v1
kind: Service
metadata:
# svc名称
name: nginx-service
spec:
#类型,可以为NodePort、LoadBalance
type: ClusterIP
selector:
# 通过标签绑定pod
app: nginx
ports:
- name: http
# 对外暴露端口
port: 80
# pod端口
targetPort: 80
# 部署
kubectl apply -f nginx-service.yaml
#查看
kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.1.0.1 <none> 443/TCP 25d
nginx-service ClusterIP 10.1.133.58 <none> 80/TCP 5d19h
nginx-service-test NodePort 10.1.71.52 <none> 80:30191/TCP 45h
#访问
# ClusterIP方式
curl 10.1.133.58
# NodePort方式
curl 192.168.3.217:30191
curl 192.168.3.218:30191
curl 192.168.3.219:30191
但是此时kubernetes集群通过Service提供的ClusterIP访问方式只能集群内部使用,而NodePort、LoadeBalance对外访问方式属于4层TCP。如果我们想使用基于固定IP的代理多个HTTP/HTTPS服务,例如nginx,此时我们需要进一步部署ingress-nginx。
Ingress-nginx部署
#1.安装
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-0.32.0/deploy/static/provider/baremetal/deploy.yaml
# 部署
kubectl apply -f deploy.yaml
#查看
kubectl get pod -n ingress-nginx
kubectl get svc -n ingress-nginx
#2.部署nginx deployment和nginx service
vim nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
imagePullPolicy: IfNotPresent
---
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
type: ClusterIP
selector:
app: nginx
ports:
- name: http
port: 80
targetPort: 80
kubectl apply -f nginx-deployment.yaml
#3.部署nginx ingress
vim nginx-ingress.yaml
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: ingress-nginx
spec:
rules:
- host: www.test1.com
http:
paths:
- path: /
backend:
serviceName: nginx-service
servicePort: 80
kubectl apply -f nginx-ingress.yaml
[root@uvmsvr-3-217 k8s]# kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller NodePort 10.1.39.222 <none> 80:30570/TCP,443:30832/TCP 21h
ingress-nginx-controller-admission ClusterIP 10.1.254.169 <none> 443/TCP 21h
#测试,通过域名访问
curl -x 192.168.3.217:30570 www.test1.com
curl -x 192.168.3.218:30570 www.test1.com
curl -x 192.168.3.219:30570 www.test1.com
总结
k8s的知识点非常多,通过对其部署能够帮助我们更好的了解k8s的组成及运行。我们需要通过实践去深入体会k8s给我们的运维过程带来的更多可能性。