第一部分:基础概念

master:api-server等服务/操作入口。
node:proxy等,应用实际运行节点。
pod:
keepalived:高可用,VIP。
nginx:反向代理,ingress服务暴露。
……

第二部分:开始搭建

物理机(虚拟机)--主机环境准备:

1,规划:根据实际情况规划服务器配置。
如学习用的单节点部署(即M和N在同一台主机上的单M单N);
测试环境的两台主机单M单N节点;
生产环境用的多M多N节点。
确定服务器数量,并确保所有服务器在同一网段,可直接互访(网段知识自行了解)。

2,服务器配置要求:MN节点最低配置要求(M和N节点1C2G仅能勉强运行起集群,部署应用等体验非常差,建议4C4G及以上起步)。

3,部署阶段要求均可访问外部网络;允许外部网络访问集群服务需要在网络入口上进行端口映射(此部分知识自行掌握)。

4,主机准备:

192.168.233.99     ==> M1

192.168.233.100   ==> M2

192.168.233.101   ==> N1

192.168.233.102   ==> N2

192.168.233.102   ==> docker仓库

5,补充网络结构拓扑图(待补)

安装过程分三部分:

一,所有节点共同操作,环境准备基础设置等;

二,M节点上操作,集群初始,高可用配置等;

三,N和其它M节点单独操作,加入集群。

【一】,所有节点共用操作,属基础环境准备阶段,部分步骤顺序不重要。如果是虚拟机安装,可在每个步骤完成后关机建立快照便于快速恢复。

系统:Centos 7.X X64 * 4 最小安装(过程略),k8s系列1.8/1.9.0/1.9.2/1.9.3,docker-ce 18/19。
1.4,1.6版本前后有比较大变化。

第1步:最小安装后的配置(使用root用户):

网络:

参考各种centos最小安装后的网络配置:

先找到当前主机的网络接口,运行ip addr 查看当前主机所有的网络接口,找到类似eth0、ens的接口。
cd /etc/sysconfig/network-scripts && ll
找到命名为ifcfg-XXX的配置文件,如此处为ifcfg-eth0
vi /etc/sysconfig/network-scripts/ifcfg-XXX
编辑此配置文件,ipaddr,netmask,gateway,dns1,dns2整行的为添加的内容,bootproto=static;onboot=yes;
(每台主机操作,IP依次分配即可,不要与内网其它主机冲突,保存退出)。此处为: vi /etc/sysconfig/network-scripts/ifcfg-eth0

TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=static
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=eth0
UUID=2ccee760-be93-4bf2-a9bd-06028b57d45b
DEVICE=eth0
ONBOOT=yes
IPADDR=192.168.233.100
NETMASK=255.255.255.0
GATEWAY=192.168.233.1
DNS1=114.114.114.114
DNS2=8.8.8.8
重启网络服务以生效。

systemctl restart network

第2步:配置主机名(每台主机功能角色确认后分别执行)

hostnamectl set-hostname k8sm1
hostnamectl set-hostname k8sm2
hostnamectl set-hostname k8sn1
hostnamectl set-hostname k8sn2

第3步:配置本机HOSTS文件,解析主机名到对应IP地址(rqw.githubusercontent.com按实际查到的IP添加解析)。

cat <<EOF >> /etc/hosts

192.168.233.99 k8sm1
192.168.233.100 k8sm2
192.168.233.101 k8sn1
192.168.233.102 k8sn2
199.232.68.133 raw.githubusercontent.com
EOF

ping k8sm1及各节点测试能否正常返回对应IP。

第4步 :各节点时区设置为+8及时间同步

timedatectl set-timezone Asia/Shanghai
timedatectl set-local-rtc 0
systemctl restart rsyslog
systemctl restart crond

yum install -y ntpdate
/usr/sbin/ntpdate ntp1.aliyun.com

第5步:升级内核(可能是3.10.0版本,升级为4.x版本。更新方法多种不一定非是这种方式)
uname -r
查看当前版本
(K8s新版本和centos系统旧版本内核搭配有问题,需要耐心等。)
载入公钥
rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
yum install -y https://www.elrepo.org/elrepo-release-7.0-4.el7.elrepo.noarch.rpm
安装长期支持版本
yum --enablerepo=elrepo-kernel install -y kernel-lt
安装完成之后设置从新内核启动:
new_core=`ls -lt /lib/modules|grep ^d | awk '{print $NF}'|grep ^4.4`
grub2-set-default 'CentOS Linux ('$new_core') 7 (Core)'
重启
reboot
【可选:安装新版本工具包
如果安装lt版本执行:
yum --disablerepo=* --enablerepo=elrepo-kernel install kernel-lt-tools】

第6 步:,启用EPEL源(软件包较新),安装依赖包及常用相关工具。
yum install -y epel-release
yum repolis
yum check-update
安装常用工具
yum install -y screen conntrack ntp ipvsadm ipset jq iptables curl sysstat libseccomp wget vim net-tools git

第7步:关闭防火墙,SELINUX(k8s目前不支持该功能,必须关闭)
systemctl stop firewalld
systemctl disable firewalld
setenforce 0 && sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config
关闭无关服务
systemctl stop postfix
systemctl disable postfix

第7步:安装iptables(操作netfilter的工具)

yum -y install iptables-services
systemctl start iptables
systemctl enable iptables
iptables -F
#清除所有规则
service iptables save

第8步 关闭swap
swapoff -a && sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab

第9步 调整centos内核参数,iptables必须调整(原文复制的)
cat > /etc/sysctl.d/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 #由于tcp_tw_recycle与kubernetes的NAT冲突,必须关闭!否则会导致服务不通。
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 #关闭不使用的ipv6协议栈,防止触发docker BUG.
net.netfilter.nf_conntrack_max=2310720
EOF
#执行以生效文件:
sysctl -p /etc/sysctl.d/kubernetes.conf

第8 步:安装docker-ce,使用阿里仓。
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 makecache fast
#yum update -y --exclude=kube*
yum install -y docker-ce
systemctl enable docker

第9 步:创建docker配置文件(daemon.json)

mkdir -p /etc/docker

cat > /etc/docker/daemon.json <<EOF
{
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"registry-mirrors": ["https://docker.mirrors.ustc.edu.cn","http://hub-mirror.c.163.com","https://cr.console.aliyun.com","https://registry.docker-cn.com"],
"insecure-registries" : ["192.168.233.102"]
}
EOF
注释:
#"insecure-registries" : ["192.168.233.102"]:配置本地docker镜像仓,本处使用了harbor,安装过程略,这样就可以推送docker镜像到本地仓再拉取。
docker login 192.168.233.102
输入用户名密码或以其它方式免登仓库。

【可选】更改docker镜像存放目录:略。

重加载配置,设置为服务项并重启docker
systemctl daemon-reload 
systemctl start docker
systemctl enable docker

第10步:安装Kubeadm(使用阿里或国内源,注意版本匹配1.6,1.8,1.9匹配相应版本)

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

yum -y install kubeadm kubelet kubectl

systemctl enable kubelet
systemctl start kubelet
kubectl get pods --all-namespaces 
#在没有安装网络前:coredns处于pending状态
注:kubectl只需要安装在M节点。
此时Kubelet服务还无法正常启动运行,等kubeadm初始化之后才会正常。以上是所有节点共有操作。

【二】M节点操作,初始化M节点,集群等。(强烈建议etcd服务为奇数个)

前置补充:k8s集群需要多M节点的在kubeadm初始化时就必须指定集群入口地址,便于其它M节点加入。如果在初始化时没有指定多M点的参数,就成了单M节点的集群,后续无法再次修改。

但如果直接使用单节点地址,一旦该主机失效就会影响集群的运转,所以在主机之前增设一套keepalived,使用keepalived的VIP地址作为集群初始化和注册入口地址以避免单点故障。keepalived安装略,VIP:192.168.233.109。
额外补充:
kubeadm安装时是将k8s所有组件容器化,所以需要各个组件的镜像。
kubeadm config images list

k8s.gcr.io/kube-apiserver:v1.19.2
k8s.gcr.io/kube-controller-manager:v1.19.2
k8s.gcr.io/kube-scheduler:v1.19.2
k8s.gcr.io/kube-proxy:v1.19.2
k8s.gcr.io/pause:3.2
k8s.gcr.io/etcd:3.4.13-0
k8s.gcr.io/coredns:1.7.0
直接下载镜像比较难成功,参考科学上网,镜像加速或其它方式获取镜像,推送本地仓一次,其它节点或再次部署可从本地仓拉取。

第1步:集群初始化,注意版本匹配,前面安装完成后的版本号,地址端口,集群内部网段。

kubeadm init --kubernetes-version=1.19.2 --control-plane-endpoint=192.168.233.109:6443 --apiserver-advertise-address=192.168.233.109 --image-repository registry.aliyuncs.com/google_containers --service-cidr=10.1.0.0/16 --pod-network-cidr=10.244.0.0/16 --upload-certs
参数解释:
--kubernetes-version=1.19.2  #版本
--control-plane-endpoint=192.168.233.109:6443 #控制面板终结点
--apiserver-advertise-address=192.168.233.109 #apiserver地址
--image-repository registry.aliyuncs.com/google_containers #镜像仓
--service-cidr=10.1.0.0/16 #service网络配置
--pod-network-cidr=10.244.0.0/16 #POD网络配置
--upload-certs #更新证书

初始化完成后会输出两条join命令及配置命令复制执行即可:
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config


第一条是给其它M节点加入使用的,第二条是给其它N节点加入使用的,保存备用,该token有24小时有效期。重新生成使用:
kubeadm token create --print-join-command

第2步:集群网络插件安装flunnel。flunnel或calico等其它网络组件。先安装网络组件再加入。

wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

查看yml文件获取所需镜像

cat kube-flannel.yml |grep image|uniq

镜像需求:image: quay.io/coreos/flannel:v0.13.0-amd64

国内直接下载基本上不会成功,从这里开始获取很多国外镜像的变通方法。

第1种:从国内查找,拉取接近的镜像,然后用docker tag标记为对应的image。

docker pull registry.cn-shanghai.aliyuncs.com/yijindami/flannel:v0.12.0-amd64

第2种:修改Yml文件,改为国内地址,两种方法任选其一即可。

安装flannel:
kubectl apply -f kube-flannel.yml

【第三部分非主M和N节点加入操作】

在非初始化的M节点加入:

  kubeadm join 192.168.233.109:6443 --token 3crvk2.22yi7njgm9yqkorr \
    --discovery-token-ca-cert-hash sha256:1c8216fe8d69699fe36ef373a75ae32c1cfcc6528084fc5d7528245f7bef180b \
    --control-plane --certificate-key 29b1326defe28f4f7f02a757523c4384bbaafa6c4c12511f7a299ca738a72eb4

在所有N节操作加入

kubeadm join 192.168.233.109:6443 --token cr9psd.2faufmg7vf0uqnri --discovery-token-ca-cert-hash sha256:ecc1a82f3804cb16bf24c38d02c3f24a8b58a96f3e45fec9d00e9d48f35185df


查看POD运行:

kubectl get pod --all-namespaces -o wide

kubectl get nodes

查看所有M和N节点都处于ready状态表示 网络组件安装成功。

至此,集群基本安装完成,中间可能会出现很多各种各样的问题,没有一一记录到。


第三部分:应用组件部署:
预备资料:
命名空间:区分和隔离资源的一种方式,操作时不加-n 参数表示默认命名空间 default。

kubectl 命令行控制工具,与apiserver交互,默认在M节点上操作。
kubectl apply -f XXX.yaml
根据资源清单配置来创建或更新pod/service/daemonset/deployment/ingress/configmap/namespace等一切文件中定义的内容。
kubectl delete -f XXX.yaml
与上操作相反,删除定义的资源类型,部分资源会删除不成功。
kubectl get 资源类型 -n 命名空间 -o wide
查看集群中某命名空间中的指定资源类型并以扩展的方式显示详细信息
kubectl describe podsname
查看pod详细信息包括日志输出等。
kubectl logs -n 命名空间 podname
查看日志
kubectl exec -it -n 命名空间 podname
进入pod中,与docker exec -it 命令一样。
yaml:资源清单定义文件。
apiversion:资源清单中的版本,各种服务应用类型的版本都不太一样,和k8s版本的相兼容度也不同,所以会出现不同版本的yaml不能完全通用的情况。


服务暴露方式:
1,nodeport:即在node节点上映射一个端口到服务上,在外部通过node节点的IP来访问。属于四层流量调度。
2,hostport:在宿主机NODE上直接暴露和服务一样的端口。
3,ingress:类似nginx通过url匹配的方式进行转发和服务暴露,属七层流量调度。类似广域网访问局域网,通过内网的端口映射,nginx转发到内网不同服务器上。

 

部署一个应用的常用步骤:
1,编写yaml资源清单,定义namespace,应用类型,service,使用镜像,暴露端口,存储挂载等等等。
2,应用yaml资源清单。
3,查看运行状态,处理异常。最多的异常是镜像拉取失败。从官方获取的yaml大部分配置的都是国外镜像地址。
4,修改更新apply。
5,服务暴露访问测试。

 

【一】dashboard,查看,编辑资源清单,集群各种资源运行情况,日志等操作。
查看当前版本:
https://github.com/kubernetes/dashboard/releases
wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-rc5/aio/deploy/recommended.yaml
wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.3-rc5/aio/deploy/recommended.yaml
wget https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.4/aio/deploy/recommended.yaml
获取yaml资源清单文件,并进行编辑,开放nodeport端口用于外部访问。
vim recommended.yaml
可以看到命名空间默认是kube-system
修改
service type: NodePort;
nodeport: 30002
kubectp apply -f recommended.yaml

创建dashboard的管理用户
kubectl create serviceaccount dashboard-admin -n kube-system
绑定用户为集群的管理员
kubectl create clusterrolebinding dashboard-cluster-admin --clusterrole=cluster-admin --serviceaccount=kube-system:dashboard-admin
获取刚刚创建的用户Token,先获取用户
kubectl get secrets -n kube-system | grep dashboard-admin

dashboard-admin-token-8nrqp
再获取token
kubectl describe secrets -n kube-system dashboard-admin-token-8nrqp

输出访问token
即可通过https://任意节点IP:30002访问到dashboard,使用token登陆即可。
 

【二】Ingress
服务暴露的方法之一,其配套组件可以是nginx,traefik等。此处使用nginx-ingress。

wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/mandatory.yaml
kubectl apply -f mandatory.yaml

未指定端口则会使用随机端口。
添加mandatory-service.yaml
手写:80和443端口分别暴露在集群的不同端口上。
cat > mandatory-service.yaml << "EOF"
apiVersion: v1
kind: Service
metadata:
  name: ingress-nginx
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
spec:
  type: NodePort
  ports:
    - name: http
      port: 80
      protocol: TCP
    - name: https
      port: 443
      protocol: TCP
  selector:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
EOF

应用部署:
kubectl apply -f mandatory-service.yaml
kubectl get svc -n ingress-nginx
查看到ingress所暴露出来的端口有80和443分别对应的,在每个node上都有监听,通过任意集群节点任意IP都可访问,为统一入口简化及高可用,可以使用keepalived的VIP做为集群整体入口,也可以用前置nginx负载均衡的方式转发/到集群所有节点IP的ingress端口上。此处的keepalived+nginx+nginx-ingress+service+pod形成整套访问及负载均衡路径。

因为ingress实际上也是一个K8s的应用,运行在集群内,它本身也需要将入口暴露出来才能被外界所访问,外界再通过它的规则去访问集群内部其它没有通过端口等形式直接暴露的服务。

ingress通过URL转发到服务例:apiVersion版本决定了其中编写规则,与旧版本中的service节的规则不太一样。官方文档也没看到有这个版本的写法。
假设已经内部建立一个服务监听在service:httpd;port:80;上

httpd-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: httpd
  namespace: default
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - http:
      paths:
      - path: /httpd
        pathType: Prefix
        backend:
          service:
            name: httpd
            port:
              number: 80

kubectl apply -f httpd-ingress.yaml
应用后,外部即可通过233.109/httpd访问到集群内的httpd服务。和nginx规则非常类似,实际上也就是nginx和ingress-controller的结合。

【三】应用部署,分后端服务和前端服务两种。
其实和前面的Ingress一样,需要一个yaml资源清单,镜像包(jar包或其它包的Docker镜像即可,指定端口,service,部署类型等,再创建ingress转发规则即可。
jar包通常基于java8或openjdk8等作为基础镜像,添加jar包和启动jar包的命令参数。
前端包通常用基于nginx的,将前端文件放到nginx容器的html目录通过80端口访问。
模板文件:
后端:springboot jar包项目例:
一共4个文件:Dockerfile,builddockerimage.sh,appdemo.yaml
application.yml提前创建为configmap,在yaml文件中调用,实现配置文件外挂。
kubectl create configmap -n namespace aps-testconfig --from-file=application.yml

1,Dockerfile例:这个jdk镜像包较小,传入参数port用于端口暴露,SHELL脚本调用创建docker镜像。
FROM 192.168.233.102/public/openjdk:8-jdk-alpine
LABEL maintainer  hxq
ARG port
EXPOSE $port
ENTRYPOINT [ "sh", "-c", "java -Duser.timezone=GMT+08 -Dfile.encoding=utf-8  -jar /app.jar" ]


2,builddockerimage.sh
参数传入镜像名称和端口调用上面的dockerfile,并推送本地私仓。
imagename=$1
port=$2 #port
harbor=192.168.233.102
if [ "x$imagename" = "x" ] ; then echo imagename must be set! ; exit 1; else echo ----imagename is:  $imagename ; fi
if [ "x$port" = "x" ] ; then echo port must set! ;exit 1; else echo ----imagename is:  $imagename ; fi
docker build -t $harbor/public/$1 . --build-arg port=$2
docker push  $harbor/public/$1

3,appdemo.yaml
将多个配置写在同一个文件内,用---分隔,也可单独写在多个文件中分别apply。
kind: Deployment
apiVersion: apps/v1
metadata:
  name: aps-test
  namespace: mes
spec:
  replicas: 2
  selector:
    matchLabels:
      app: aps-test
  template:
    metadata:
      labels:
        app: aps-test
    spec:
      containers:
      - name: aps-test
        image: 192.168.233.102/public/aps-test
        volumeMounts:
        - name: appconfig
          mountPath: /config
          readOnly: true
      volumes:
      - name: appconfig
        configMap:  #挂载configmap,使用name定位。
          name: aps-testconfig
---
apiVersion: v1
kind: Service
metadata:
  name: aps-test
  namespace: mes
spec:
  selector:
    app: aps-test
  ports:
  - protocol: TCP
    port: 8395
    targetPort: 8395
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: aps-test
  namespace: mes
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  rules:
  - http:
      paths:
      - path: /aps-test(/|$)(.*)
        pathType: Prefix
        backend:
          service:
            name: aps-test
            port:
              number: 8395

  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
ingress转发规则配置,用这个方式实现将该URL下的所有请求都转到对应的服务上,否则会出现二级路径访问还是只能到根路径的问题。

路径匹配规则的问题:pathType::官方文档中说明有几种类型的pathType,

https://kubernetes.io/zh/docs/concepts/services-networking/ingress/

Exact  完全匹配
Prefix  前缀匹配

0.22.0版本之后需要使用rewrite进行重写。

https://docs.pivotal.io/pks/1-7/nsxt-ingress-rewrite-url.html

另一种rewrite方法:

    nginx.ingress.kubernetes.io/rewrite-target: /$1

- path: /aps-test/(.*)

也可以实现。

前端项目基本同上,比后端项目简单,不用挂载配置文件等操作,略。

 

 

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐