n@TOC
1、环境准备(至少2核)
1.1 主机名
分别设置主机名
hostnamectl set-hostname m1
hostnamectl set-hostname n1
hostnamectl set-hostname n2
1.2 hosts
配置各节点映射,以及flannel下载时的网络映射。
192.168.66.20 m1
192.168.66.21 n1
192.168.66.22 n2
#199.232.68.133 raw.githubusercontent.com
1.3 依赖包
yum install -y conntrack ntpdate ntp ipvsadm ipset jq iptables curl sysstat libseccomp wget vim net-tools git
1.4 防火墙
systemctl stop firewalld && systemctl disable firewalld
设置规则为空
yum -y install iptables-services && systemctl start iptables && systemctl enable iptables && iptables -F && service iptables save
1.5 SELINUX
setenforce 0 && sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config
1.6 交换空间
swapoff -a && sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
1.7 内核参数
cat > kubernetes.conf <<EOF
net.bridge.bridge-nf-call-iptables=1
net.bridge.bridge-nf-call-ip6tables=1
net.ipv4.ip_forward=1
net.ipv4.tcp_tw_recycle=0
vm.swappiness=0 # 禁止使用 swap 空间,只有当系统 OOM 时才允许使用它
vm.overcommit_memory=1 # 不检查物理内存是否够用
vm.panic_on_oom=0 # 开启 OOM
fs.inotify.max_user_instances=8192
fs.inotify.max_user_watches=1048576
fs.file-max=52706963
fs.nr_open=52706963
net.ipv6.conf.all.disable_ipv6=1
net.netfilter.nf_conntrack_max=2310720
EOF
cp kubernetes.conf /etc/sysctl.d/kubernetes.conf
sysctl -p /etc/sysctl.d/kubernetes.conf
1.8 rsyslogd、systemd journald
创建持久化保存日志的目录
mkdir /var/log/journal
mkdir /etc/systemd/journald.conf.d
cat > /etc/systemd/journald.conf.d/99-prophet.conf <<EOF
[Journal]
# 持久化保存到磁盘
Storage=persistent
# 压缩历史日志
Compress=yes
SyncIntervalSec=5m
RateLimitInterval=30s
RateLimitBurst=1000
# 最大占用空间 10G
SystemMaxUse=10G
# 单日志文件最大 200M
SystemMaxFileSize=200M
# 日志保存时间 2 周
MaxRetentionSec=2week
# 不将日志转发到 syslog
ForwardToSyslog=no
EOF
systemctl restart systemd-journald
1.9 内核升级
升级原因:CentOS 7.x 系统自带的 3.10.x 内核存在一些 Bugs,导致运行的 Docker、Kubernetes 不稳定。
① 下载rpm
rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-3.el7.elrepo.noarch.rpm
② 安装
安装完成后检查 /boot/grub2/grub.cfg 中对应内核 menuentry 中是否包含 initrd16 配置,如果没有再安装一次!
yum --enablerepo=elrepo-kernel install -y kernel-lt
③ 设置内核
grub2-set-default 'CentOS Linux (4.4.189-1.el7.elrepo.x86_64) 7 (Core)'
2 Kubeadm部署安装
本节中2.1、2.2和2.3步各节点都要执行
2.1 kube-proxy开启ipvs的前置条件
模块加载
modprobe br_netfilter
cat > /etc/sysconfig/modules/ipvs.modules <<EOF
#!/bin/bash
modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr
modprobe -- ip_vs_sh
modprobe -- nf_conntrack_ipv4
EOF
赋予权限
chmod 755 /etc/sysconfig/modules/ipvs.modules
2.2 docker安装
yum install -y yum-utils device-mapper-persistent-data lvm2
yum-config-manager \
--add-repo \
http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
yum update -y && yum install -y docker-ce-18.09.5-3.el7
## 创建 /etc/docker 目录
mkdir /etc/docker
# 配置 daemon
cat > /etc/docker/daemon.json <<EOF
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
}
}
EOF
mkdir -p /etc/systemd/system/docker.service.d
# 重启docker服务
systemctl daemon-reload && systemctl restart docker && systemctl enable docker
2.3 Kubeadm安装(主从配置)
各个服务器都执行下面的操作。
离线安装docker的镜像
1.先下载好准备的文件(👇) 后解压,解压指令:tar -zvxf 文件名
文件链接:https://pan.baidu.com/s/1re9043zu6qq4UuElBAw2sg 提取码:gvmx
2.编写安装脚本
vi load-images.sh
==================================================
脚本内容如下:
#!/bin/bash
ls /root/kubeadm-basic.images > /tmp/images-list.txt
cd /root/kubeadm-basic.images
for i in $( cat /tmp/images-list.txt )
do
docker load -i $i
done
rm -rf /tmp/images-list.txt
==================================================
3.赋予权限并执行脚本
chmod a+x load-images.sh && ./load-images.sh
提示:
上面的安装包脚本等都可以通过scp传到其它子节点服务器上。
如:scp -r kubeadm-basic.images load-images.sh root@192.168.149.129:/root/
配置源
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
安装kubeadm、kubectl和kubelet
yum -y install kubeadm-1.15.1 kubectl-1.15.1 kubelet-1.15.1
systemctl enable kubelet.service
2.4 初始化主节点
生成配置文件
kubeadm config print init-defaults > kubeadm-config.yaml
修改配置文件
vi kubeadm-config.yaml
修改内容如下:
第12行配置主节点IP地址
第34行修改版本为 v.1.15.1
第37行新增 podSubnet: “10.244.0.0/16”
并在尾末加入下方配置:
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
featureGates:
SupportIPVSProxyMode: true
mode: ipvs
执行
kubeadm init --config=kubeadm-config.yaml --experimental-upload-certs | tee kubeadm-init.log
查看日志
cat kubeadm-init.log
根据日志提示需要我们执行的命令如下:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
mkdir -p /usr/local/install-k8s/core && mkdir -p /usr/local/install-k8s/plugin/flannel
mv kubeadm-init.log kubeadm-config.yaml /usr/local/install-k8s/core
kubeadm token create --ttl 0 --print-join-command
2.5 网络部署
下载kube-flannel.yml
如果提示下载失败,请配置hosts:
sudo vi /etc/hosts
199.232.68.133 raw.githubusercontent.com
mkdir -p /root/install-k8s/core
mv kubeadm-init.log kubeadm-config.yaml install-k8s/core
mkdir -p /root/install-k8s/plugin/flannel
cd /root/install-k8s/plugin/flannel
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
kubectl create -f kube-flannel.yml
查看组件
kubectl get pod -n kube-system -o wide
注意:如果安装了flannel但是状态一直是Init:0/1,那么可以删除掉这个pod,会重新安装一个,状态过一会就成了Running,节点状态也成了Ready。
删除pod:
kubectl delete pod kube-flannel-ds-dbvxm -n kube-system
kube-flannel.yml
---
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: psp.flannel.unprivileged
annotations:
seccomp.security.alpha.kubernetes.io/allowedProfileNames: docker/default
seccomp.security.alpha.kubernetes.io/defaultProfileName: docker/default
apparmor.security.beta.kubernetes.io/allowedProfileNames: runtime/default
apparmor.security.beta.kubernetes.io/defaultProfileName: runtime/default
spec:
privileged: false
volumes:
- configMap
- secret
- emptyDir
- hostPath
allowedHostPaths:
- pathPrefix: "/etc/cni/net.d"
- pathPrefix: "/etc/kube-flannel"
- pathPrefix: "/run/flannel"
readOnlyRootFilesystem: false
# Users and groups
runAsUser:
rule: RunAsAny
supplementalGroups:
rule: RunAsAny
fsGroup:
rule: RunAsAny
# Privilege Escalation
allowPrivilegeEscalation: false
defaultAllowPrivilegeEscalation: false
# Capabilities
allowedCapabilities: ['NET_ADMIN', 'NET_RAW']
defaultAddCapabilities: []
requiredDropCapabilities: []
# Host namespaces
hostPID: false
hostIPC: false
hostNetwork: true
hostPorts:
- min: 0
max: 65535
# SELinux
seLinux:
# SELinux is unused in CaaSP
rule: 'RunAsAny'
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: flannel
rules:
- apiGroups: ['extensions']
resources: ['podsecuritypolicies']
verbs: ['use']
resourceNames: ['psp.flannel.unprivileged']
- apiGroups:
- ""
resources:
- pods
verbs:
- get
- apiGroups:
- ""
resources:
- nodes
verbs:
- list
- watch
- apiGroups:
- ""
resources:
- nodes/status
verbs:
- patch
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: flannel
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: flannel
subjects:
- kind: ServiceAccount
name: flannel
namespace: kube-system
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: flannel
namespace: kube-system
---
kind: ConfigMap
apiVersion: v1
metadata:
name: kube-flannel-cfg
namespace: kube-system
labels:
tier: node
app: flannel
data:
cni-conf.json: |
{
"name": "cbr0",
"cniVersion": "0.3.1",
"plugins": [
{
"type": "flannel",
"delegate": {
"hairpinMode": true,
"isDefaultGateway": true
}
},
{
"type": "portmap",
"capabilities": {
"portMappings": true
}
}
]
}
net-conf.json: |
{
"Network": "10.244.0.0/16",
"Backend": {
"Type": "vxlan"
}
}
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: kube-flannel-ds
namespace: kube-system
labels:
tier: node
app: flannel
spec:
selector:
matchLabels:
app: flannel
template:
metadata:
labels:
tier: node
app: flannel
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/os
operator: In
values:
- linux
hostNetwork: true
priorityClassName: system-node-critical
tolerations:
- operator: Exists
effect: NoSchedule
serviceAccountName: flannel
initContainers:
- name: install-cni-plugin
#image: flannelcni/flannel-cni-plugin:v1.0.1 for ppc64le and mips64le (dockerhub limitations may apply)
image: rancher/mirrored-flannelcni-flannel-cni-plugin:v1.0.1
command:
- cp
args:
- -f
- /flannel
- /opt/cni/bin/flannel
volumeMounts:
- name: cni-plugin
mountPath: /opt/cni/bin
- name: install-cni
#image: flannelcni/flannel:v0.17.0 for ppc64le and mips64le (dockerhub limitations may apply)
image: rancher/mirrored-flannelcni-flannel:v0.17.0
command:
- cp
args:
- -f
- /etc/kube-flannel/cni-conf.json
- /etc/cni/net.d/10-flannel.conflist
volumeMounts:
- name: cni
mountPath: /etc/cni/net.d
- name: flannel-cfg
mountPath: /etc/kube-flannel/
containers:
- name: kube-flannel
#image: flannelcni/flannel:v0.17.0 for ppc64le and mips64le (dockerhub limitations may apply)
image: rancher/mirrored-flannelcni-flannel:v0.17.0
command:
- /opt/bin/flanneld
args:
- --ip-masq
- --kube-subnet-mgr
resources:
requests:
cpu: "100m"
memory: "50Mi"
limits:
cpu: "100m"
memory: "50Mi"
securityContext:
privileged: false
capabilities:
add: ["NET_ADMIN", "NET_RAW"]
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: EVENT_QUEUE_DEPTH
value: "5000"
volumeMounts:
- name: run
mountPath: /run/flannel
- name: flannel-cfg
mountPath: /etc/kube-flannel/
- name: xtables-lock
mountPath: /run/xtables.lock
volumes:
- name: run
hostPath:
path: /run/flannel
- name: cni-plugin
hostPath:
path: /opt/cni/bin
- name: cni
hostPath:
path: /etc/cni/net.d
- name: flannel-cfg
configMap:
name: kube-flannel-cfg
- name: xtables-lock
hostPath:
path: /run/xtables.lock
type: FileOrCreate
2.6 子节点加入
接下来就是让另外的子节点加入到主节点。命令在init的log中。
cd …/…/core/ && vi kubeadm-init.log
进入日志后的最后一行。
在子节点服务器上执行,加入主节点的命令
回到主节点服务器查看节点状况
kubectl get node
现在两个节点都是NotReady,可以查看pod的网络是否准备好了
kubectl get pod -n kube-system -o wide
过一会pod的状态会从Init变成Running,发现集群状态也正常了,如果一直不变,就delete,会自带重新创建一个新的pod。
3 配置私有仓库
3.1 修改/etc/docker/daemon.json
“insecure-registries”: [“www.xiaosi.com”]
3.2 Docker-compose安装
curl -L https://get.daocloud.io/docker/compose/releases/download/1.25.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
tar -zxvf harbor-offline-installer-v1.2.0.tgz
修改解压目录harbor下的harbor.cfg
第5行:修改刚刚daemon.json的url(具体看第一步)
第9行:改成https 也是根据daemon.json的url配置来的
3.2.证书创建
mkdir -p /data/cert/ && cd /data/cert
openssl genrsa -des3 -out server.key 2048 生成私钥并设置密码
openssl req -new -key server.key -out server.csr 密码输入刚刚生成的私钥密码
cp server.key server.key.org
openssl rsa -in server.key.org -out server.key
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt 签名
chmod a+x * 赋予权限
cd /usr/local/harbor/
修改所有服务器(所有节点以及hub这台)的hosts
vi /etc/hosts
./install.sh
4、k8s使用
1.创建pod
格式:kubectl run pod名 --image==docker镜像 --port=80 --replicas=副本数(奇数个)
kubectl run nginx-demo --image==hub.elwin.com/library/myapp:v1 --port=80 --replicas=1
2.查看rs
kubectl get rs
3.查看pod
kubectl get pod -o wide
kubectl get po -n kube-system -o wide
4.删除pod
kubectl delete pod pod名
5.修改副本数
kubectl scale --replicas=3 deployment/myapp
6.pod负载均衡
当有多个副本提供服务时,k8s提供了统一一个ip来进行自动负载均衡。
kubectl expose deployment myapp --port=30000 --target-port=80
7.获取svc
kubectl get svc
8.对外提供访问
根据获取的svc名进行对应的修改
kubectl edit svc myapp
修改type为NodePort
外部可以通过当前服务器ip+映射端口访问,如上图就是http://192.168.149.128:30764/
ipvsadm -Ln
kubectl expose deployment my-deployment --port=30000 --target-port=80
kubectl edit svc nginx-deployment
5 pods
5.1 pod基本概念
可以创建和管理的最先单元
包含多个容器,即在一个pod中可以安装多个docker容器
pod中容器与容器之间网络是互通的
生命周期短暂比如,当 Pod 所在节点发生故障,那么该节点上的 Pod
会被调度到其他节点,但需要注意的是,被重新调度的 Pod 是一个全新的 Pod,跟之前的
Pod 没有半毛钱关系
5.2 pod的实现机制
每个 Pod 中有一个 Pause 容器保存所有的容器状态。通过管理 pause 容器,达到管理 pod 中所有容器的效果。
共享网络:
多个容器共享同一 network namespace,由此在一个 Pod 里的多个容器共享 Pod 的 IP 和端口 namespace,所以一个 Pod 内的多个容器之间可以通过 localhost 来进行通信,但需要注意的是容器间的端口不要冲突。
共享存储:
容器间存储是共享的,使用数据卷进行持久化存储。
5.3 镜像拉取
pod里是由一个或多个容器组成,那么我们可以指定要拉取的镜像。
拉取策略
IfNotPresent: 默认值。镜像在宿主机上不存在时拉取,但:latest标签的镜像默认为Always
Always: 每次创建都会去拉取镜像
Nerver: 永远不主动拉取这个镜像
参数 | 说明 |
---|---|
spec.containers[].image | 镜像拉取地址以及版本 |
spec.containers[].name | 容器名称 |
spec.containers[].imagePullPolicy | 拉取策略 |
如:
apiVersion: v1
kind: Deployment
metadata:
name: web
spec:
containers:
- image: nginx
name: nginx
imagePullPolicy: IfNotPresent
5.4 pod资源限制
pod设置可以将请求调度到资源充足的Node上,limit设置上限。
参数 | 说明 |
---|---|
spec.containers[].resources.requests.cpu | 调度请求的CPU,可以超过 |
spec.containers[].resources.requests.memory | 调度请求的内存,可以超过;但如果超过,容器可能会在Node内存不足时清理 |
spec.containers[].resources.limits.cpu | CPU上限,可以短暂超过,容器也不会被停止 |
spec.containers[].resources.limits.memory | 内存上限,不可以超过;如果超过,容器可能会被停止或调度到其他资源充足的机器上 |
如:
apiVersion: v1
kind: Deployment
metadata:
name: web
spec:
containers:
- image: nginx
name: nginx
resources:
requests:
cpu: “300m”
memory: “56Mi”
limits:
cpu: “500m”
memory: “128Mi”
5.5 重启策略
此处重启是指在Pod所在Node上面本地重启,并不会调度到其他Node上去。
RestartPolicy
Always:只要退出就重启,默认策略
OnFailure:失败退出(exit code不等于0)时重启
Never:只要退出就不再重启
参数 | 说明 |
---|---|
spec.restartPolicy | 重启策略 |
如:
apiVersion: v1
kind: Deployment
metadata:
name: web
spec:
restartPolicy: Always
5.6 调度策略
资源设置可以影响pod调度,详细请看上面的第6.4节。 本次主要说明 节点选择器 影响pod调度。
有时候我们想让某些服务部署在指定节点上,那么我们可以用节点选择器实现。
首先指定node节点标签,如:叫node1叫dev,叫node2叫test。如果说node节点标签已经起名字了,就再加个–overwrite
kubectl label nodes <节点名> disktype=<标签名> [–overwrite]
再指定yaml的节点选择器,只让该pod在指定节点上生成。
参数 | 说明 |
---|---|
spec.nodeSelector.disktype | 节点选择 |
如:
apiVersion: v1
kind: Deployment
metadata:
name: web
spec:
nodeSelector:
disktype: dev
5.7 快速生成模板yaml文件
kubectl create deployment web --image=nginx -o yaml --dry-run >my.yaml
5.8 将已经生成的pod转存yaml
kubectl get deployment myapp -o=yaml --export >myapp.yaml
5.9 根据yaml文件创建pod
kubectl create -f myapp.yaml
6、controller
6.1.简单介绍
管理和运行容器的对象。Kubernetes 通过各种 Controller 来管理 Pod 的生命周期。为了满足不同业务场景,Kubernetes 开发了 Deployment、ReplicaSet、DaemonSet、StatefuleSet、Job 等多种 Controller
6.2. Deployment
7、安装时遇到的问题
1.子节点加入主节点的时候加入不进去
报错:error execution phase preflight: unable to fetch the kubeadm-config ConfigMap
解决方案:因为主节点的token过期了,重新生成不过期的token,用新的token加入即可。
生成命令:
kubeadm token create --ttl 0 --print-join-command
2. kube-flannel一直Init:0/1
显示:kube-flannel-ds-gpf6l 0/1 Init:0/1
解决方案:删除该pod,自动重新生成。或者继续等待
删除命令:
kubectl delete pod kube-flannel-ds-xxxx -n kube-system
- kube-flannel.yml文件下载不下来
解决方案:修改hosts文件,在文件末尾处新增一行添加:199.232.68.133 raw.githubusercontent.com ,后重新尝试下载。
指令:
① 修改
vi /etc/hosts
② 下载
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml