环境准备
至少两台服务器,一台装 Master,一台装 Slave,我这次使用华为云两台 ubuntu arm64 架构的服务器,安装的 kubernates 为 1.18.0
安装 docker
配置 docker
切换docker下载源为国内镜像站 以及 修改cgroups。添加 docker 配置 /etc/docker/daemon.json,registry-mirrors镜像仓库改成国内的,cgroupdriver可以把它理解成一个进程隔离工具,docker就是用它来实现容器的隔离的。docker 默认使用的是cgroupfs,而 k8s 也用到了一个进程隔离工具systemd,如果使用两个隔离组的话可能会引起异常,所以我们要把 docker 的也改成systemd。
修改daemon.json
$ vi /etc/docker/daemon.json
{
"registry-mirrors": [
"https://*hcih***.mirror.aliyuncs.com",
"https://dockerhub.azk8s.cn",
"https://reg-mirror.qiniu.com",
"https://quay-mirror.qiniu.com"
],
"exec-opts": [ "native.cgroupdriver=systemd" ]
}
保存重启 docker
$ systemctl daemon-reload
$ systemctl restart docker
安装 k8s
安装完了 docker 就可以下载 k8s 的三个主要组件kubelet、kubeadm以及kubectl了。这一步两台主机都需要进行安装。先来简单介绍一下这三者:
- kubelet: k8s 的核心服务
- kubeadm: 这个是用于快速安装 k8s 的一个集成工具,我们在master1和worker1上的 k8s 部署都将使用它来完成。
- kubectl: k8s 的命令行工具,部署完成之后后续的操作都要用它来执行
其实这三个的下载很简单,直接用apt-get就好了,但是因为某些原因,它们的下载地址不存在了。所以我们需要用国内的镜像站来下载,也很简单,依次执行下面五条命令即可:
# 使得 apt 支持 ssl 传输
apt-get update && apt-get install -y apt-transport-https
# 下载 gpg 密钥
curl https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add -
# 添加 k8s 镜像源
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF
# 更新源列表
apt-get update
# 下载 kubectl,kubeadm以及 kubelet
apt-get install -y kubelet kubeadm kubectl
初始化 Master
使用kubeadm的init命令就可以轻松的完成初始化,不过需要携带几个参数,如下。先不要直接复制执行,将赋值给–apiserver-advertise-address参数的 ip 地址修改为自己的master主机地址,然后再执行。
kubeadm init \
--apiserver-advertise-address=192.168.0.26 \
--image-repository registry.aliyuncs.com/google_containers \
--service-cidr=10.1.0.0/16 \
--pod-network-cidr=10.244.0.0/16
这里需要保证 docker 和 kubelet 的 cgroups 一致。如果遇到某个组件拉去失败的警告,比如 [ERROR ImagePull],可以尝试从别的源拉取镜像,打上对应的标签即可。我的服务器是 arm64 架构,就遇到了这个问题
一些常用参数:
- –apiserver-advertise-address: k8s 中的主要服务apiserver的部署地址,填自己的管理节点 ip
- –image-repository: 拉取的 docker 镜像源,因为初始化的时候kubeadm会去拉 k8s 的很多组件来进行部署,所以需要指定国内镜像源,下不然会拉取不到镜像。
- –pod-network-cidr: 这个是 k8s 采用的节点网络,因为我们将要使用flannel作为 k8s 的网络,所以这里填10.244.0.0/16就好
- –kubernetes-version: 这个是用来指定你要部署的 k8s 版本的,一般不用填,不过如果初始化过程中出现了因为版本不对导致的安装错误的话,可以用这个参数手动指定。
- –ignore-preflight-errors: 忽略初始化时遇到的错误,比如说我想忽略 cpu 数量不够 2 核引起的错误,就可以用–ignore-preflight-errors=CpuNum。错误名称在初始化错误时会给出来。
当你看到如下字样是,就说明初始化成功了,输出的结果给出了接下来该做什么,参照执行即可 kubectl
和 flannel
,kubeadm join 是配置 Slave 节点加入集群使用的,有效期是24小时,过期的话可以在master节点上使用kubeadm token create --print-join-command命令来重新生成一条。
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
Alternatively, if you are the root user, you can run:
export KUBECONFIG=/etc/kubernetes/admin.conf
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.0.26:6443 --token z2aihu.gvzep0o3o906xftu --discovery-token-ca-cert-hash sha256:2eac4830371ee5d7c7279c8e847ac8d04609322841f78f031d4cc2c01e0ee728
如果在初始化过程中出现了任何Error导致初始化终止了,使用kubeadm reset重置之后再重新进行初始化。
配置 kubectl
复制上面的命令即可
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
部署 flannel 网络
根据提示 kubectl apply -f [podnetwork].yaml,
kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
部署 Slave 节点
Slave 也需要安装 Docker kubelet kubeadm kubectl,根据提示执行
kubeadm join 192.168.0.26:6443 --token z2aihu.gvzep0o3o906xftu --discovery-token-ca-cert-hash sha256:2eac4830371ee5d7c7279c8e847ac8d04609322841f78f031d4cc2c01e0ee728
Slave 节点输出以下信息标识加入集群成功
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 master to see this node join the cluster.
进入 Master 验证成功
root@master:~# kubectl get nodes
NAME STATUS ROLES AGE VERSION
slave Ready <none> 40h v1.22.1
master Ready control-plane,master 45h v1.22.1
移除节点
- 排干 slave 上的 pods 资源(驱逐 salve 节点上已有的 pods 到其他节点)
kubectl drain slave --delete-local-data --force --ignore-daemonsets
- 移除 slave 节点
kubectl delete node slave
- 清除 slave 节点数据,在 slave 节点执行
kubeadm reset
部署 Ingress-nginx
点击到GitHub上取资源文件 mandatory.yaml,加上hostNetwork: true
,根据服务器架构修改一下镜像源即可;
apiVersion: v1
kind: Namespace
metadata:
name: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
---
kind: ConfigMap
apiVersion: v1
metadata:
name: nginx-configuration
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
---
kind: ConfigMap
apiVersion: v1
metadata:
name: tcp-services
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
---
kind: ConfigMap
apiVersion: v1
metadata:
name: udp-services
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: nginx-ingress-serviceaccount
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
name: nginx-ingress-clusterrole
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
rules:
- apiGroups:
- ""
resources:
- configmaps
- endpoints
- nodes
- pods
- secrets
verbs:
- list
- watch
- apiGroups:
- ""
resources:
- nodes
verbs:
- get
- apiGroups:
- ""
resources:
- services
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- events
verbs:
- create
- patch
- apiGroups:
- "extensions"
- "networking.k8s.io"
resources:
- ingresses
verbs:
- get
- list
- watch
- apiGroups:
- "extensions"
- "networking.k8s.io"
resources:
- ingresses/status
verbs:
- update
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: Role
metadata:
name: nginx-ingress-role
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
rules:
- apiGroups:
- ""
resources:
- configmaps
- pods
- secrets
- namespaces
verbs:
- get
- apiGroups:
- ""
resources:
- configmaps
resourceNames:
# Defaults to "<election-id>-<ingress-class>"
# Here: "<ingress-controller-leader>-<nginx>"
# This has to be adapted if you change either parameter
# when launching the nginx-ingress-controller.
- "ingress-controller-leader-nginx"
verbs:
- get
- update
- apiGroups:
- ""
resources:
- configmaps
verbs:
- create
- apiGroups:
- ""
resources:
- endpoints
verbs:
- get
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
name: nginx-ingress-role-nisa-binding
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: nginx-ingress-role
subjects:
- kind: ServiceAccount
name: nginx-ingress-serviceaccount
namespace: ingress-nginx
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: nginx-ingress-clusterrole-nisa-binding
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: nginx-ingress-clusterrole
subjects:
- kind: ServiceAccount
name: nginx-ingress-serviceaccount
namespace: ingress-nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-ingress-controller
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
template:
metadata:
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
annotations:
prometheus.io/port: "10254"
prometheus.io/scrape: "true"
spec:
# wait up to five minutes for the drain of connections
terminationGracePeriodSeconds: 300
serviceAccountName: nginx-ingress-serviceaccount
hostNetwork: true # 80端口是通过它暴露的
nodeSelector:
kubernetes.io/os: linux
containers:
- name: nginx-ingress-controller
image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller-arm64:0.30.0
#image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.30.0 #amd架构请打开换此镜像
args:
- /nginx-ingress-controller
- --configmap=$(POD_NAMESPACE)/nginx-configuration
- --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services
- --udp-services-configmap=$(POD_NAMESPACE)/udp-services
- --publish-service=$(POD_NAMESPACE)/ingress-nginx
- --annotations-prefix=nginx.ingress.kubernetes.io
securityContext:
allowPrivilegeEscalation: true
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
# www-data -> 101
runAsUser: 101
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
ports:
- name: http
containerPort: 80
protocol: TCP
- name: https
containerPort: 443
protocol: TCP
livenessProbe:
failureThreshold: 3
httpGet:
path: /healthz
port: 10254
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 10
readinessProbe:
failureThreshold: 3
httpGet:
path: /healthz
port: 10254
scheme: HTTP
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 10
lifecycle:
preStop:
exec:
command:
- /wait-shutdown
---
apiVersion: v1
kind: LimitRange
metadata:
name: ingress-nginx
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
spec:
limits:
- min:
memory: 90Mi
cpu: 100m
type: Container
- 执行
kubectl apply -f ingress-nginx.yaml
- 执行
kubectl get pods -n ingress-nginx
查看 ingress-nginx 命名空间下的 pods,输出以下信息代表成功
root@master:~# kubectl get pods -n ingress-nginx
NAME READY STATUS RESTARTS AGE
nginx-ingress-controller-787889c8cf-hdjkj 1/1 Running 0 68s
- 需要注意 nginx-ingress-controller 将占用 80 端口,如果启动失败可在 docker 查看容器启动日志,端口被占用会有提示,可在 Deployment 资源的容器启动参数上加上
http-port=30000
更换端口,类似的还有https-port=30001
更多原创 shellfish.top