本文介绍如何使用Kubeadm在自己的服务器上将Kubernetes应用部署为生产环境,而不使用Kuberentes云服务商。
在进行之前,我建议你先保持理智,问自己为什么需要这么做:
总之,如果你有充分的理由,请往下进行;
否则,我非常建议你使用Kubernetes云服务商。它虽然贵,但是很省心。
要按照本文方法部署Kubernetes,你需要准备服务器:
你需要准备能够随时工作于生产环境的Kubernetes应用,包括应用镜像和deployment文件。
你需要对Kubernetes和Linux操作有基本了解。
我这组合可算是把什么都踩了一遍
哥们不是开玩笑的。
如果你的系统镜像被服务商进行了魔改,建议先安装纯净的系统
比如阿里云迷之Debian12
Debian官方已经在12中把sysetmd.resolved
给移除了
但阿里云Debian12直接把sysetmd.resolved
作为默认DNS服务
也不是不行,但你要保证所有机器都使用这个。不然会出问题
如果你其它机器都是纯净系统的,我建议把阿里云那台给重装掉算了
某些镜像在第一次重启之前可能存在问题。如果你的机器从来没重启过,我建议先重启一遍。
reboot now
非常重要!
在开始前,先检测各个机器之间的连接性。
然后检查所有机器的端口开启情况。某些防火墙或者云服务器会默认关闭端口,你需要确保对应机器的以下端口是可以公开访问的:
Protocol | Direction | Port Range | Purpose | Used By |
---|---|---|---|---|
TCP | Inbound | 6443 | Kubernetes API server | All |
TCP | Inbound | 2379-2380 | etcd server client API | kube-apiserver, etcd |
TCP | Inbound | 10250 | Kubelet API | Self, Control plane |
TCP | Inbound | 10259 | kube-scheduler | Self |
TCP | Inbound | 10257 | kube-controller-manager | Self |
Protocol | Direction | Port Range | Purpose | Used By |
---|---|---|---|---|
TCP | Inbound | 10250 | Kubelet API | Self, Control plane |
TCP | Inbound | 30000-32767 | NodePort Services (default) | All |
详情请见Kubernetes文档 Ports and Protocols
提示:
你可以跳过这步,但如果出了问题,请不要忘记排查防火墙/安全组。
提供一个检测tcp连接的方法:
A主机作为服务端,开启端口的服务
nc -l -p 6443
B主机作为客户端,接通端口
nc <address-of-A> 6443
发点东西过去看看A能不能收到
Kubernetes暂时无法直接运行于开启交换区(虚拟内存)的环境,因此请确保你关闭了所有交换区。
查看是否有交换区(swap容量不为0):
free -h
关闭交换区直到关机/重启:
swapoff -a
禁止开机启动交换区:
打开以下文件
vim /etc/fstab
将里面所有交换区注释掉,示意:
#
/dev/vda1 / ext4 defaults 1 1
# /dev/vda2 swap swap defaults 0 0
如果服务器的时间不准确,可能会造成证书过期,CoreDNS失联等问题。
所以请务必保证所有服务器处于相同时区,并且与时间服务器同步时间。
设置系统时区
timedatectl set-timezone Asia/Shanghai
设置本地时钟使用UTC时间
timedatectl set-local-rtc 0
重启相关服务
systemctl restart rsyslog
systemctl restart crond
服务器的主机名称(hostname)将成为Kubernetes的结点名称。
名称无法(很难)在部署后更改,请在部署前决定每个机器的名称。
建议:
如果你是云服务商的vps机器,先看看控制面板能不能改
如果不能改或者硬件主机,按以下操作:
修改主机名
hostnamectl set-hostname <your-host-name>
修改hosts文件
vi /etc/hosts
将里面出现的所有旧名称项,都替换为新主机名
注意: 某些主机的hosts文件会有托管,此时直接修改hosts无效。请注意hosts文件是否有相关注释说明。
重新登陆ssh就可以看到新主机名
这一步需要在Master和Worker进行
请参考官方教程进行安装
按照教程安装完后,你应该会同时安装完docker和containerd
验证docker和containerd成功安装并启动:
systemctl status docker
systemctl status containerd
此步具有时效性,只保证编写时刻(2023-11-5)需要如此操作。
打开/etc/containerd/config.toml
文件,作两处修改
vi /etc/containerd/config.toml
cri
从disabled_plugins
中移除# disabled_plugins = ["cri"];
disabled_plugins = [];
version = 2
[plugins]
[plugins."io.containerd.grpc.v1.cri"]
[plugins."io.containerd.grpc.v1.cri".containerd]
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes]
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
runtime_type = "io.containerd.runc.v2"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
SystemdCgroup = true
编辑完毕后重启服务
systemctl restart containerd
这一步需要在Master和Worker进行
请参考官方教程进行安装
验证已经安装kubeadm、kubelet和kubectl
kubeadm
systemctl status kubelet
kubectl
这步仅需要在满足以下条件的机器上执行:
- 机器希望以公网身份接入网络
- 机器网卡的IP并不是机器的公网IP
请输入以下命令检测默认网卡是否为公网IP
ip route get 1.1.1.1 | grep -oP 'src \K\S+'
或者使用以下命令,观察默认网卡(比如eth0)是否存在你的公网IP
ip a
如果显示的是你的公网IP,或者你不需要公网接入,你可以跳过这一节;否则,继续往下执行。
输入以下命令,为默认网卡增加临时的IP地址。这里假设你的默认网卡名为eth0
,如果不是,你需要修改:
sudo ip addr add <公网IP>/24 dev eth0 label eth0:0
sudo ip link set dev eth0:0 up
这将持续到机器重启,重启后你需要重新创建。
关于持久化……每个镜像使用的网络服务不同,会有不同的搞法,这里就不展开了
就单纯给点提示吧:
systemctl list-unit-files | grep -i network
使用以下命令,检测公网IP是否出现在你的默认网卡中
ip a
查看kubelet的环境变量文件:
systemctl cat kubelet.service | grep EnvironmentFile
你会看到类似以下的输出:
EnvironmentFile=-/var/lib/kubelet/kubeadm-flags.env
EnvironmentFile=-/etc/default/kubelet
kubeadm官方说第一个文件是自动生成的,不建议修改。因此我们修改第二个(不存在则创建)
vi /etc/default/kubelet
在打开的文件中,指定--node-ip
参数为公网IP
KUBELET_EXTRA_ARGS=--node-ip=<公网IP>
关于这点的更多阅读资料
这一步只需要在Master进行
重要提醒:
中途出现问题可能会导致kubeadm初始化中断,你可以使用kubeadm reset
重置到初始前状态
这步需要在无法连接到
k8s.gcr.io
的Master执行(大陆机器)
如果是国内环境,很遗憾,无法访问默认的k8s.gcr.io
容器仓库。
没有关系,我们可以使用镜像仓库
此处需要将容器仓库修改为国内镜像
如果你想了解更多,请参考这里:
我们使用阿里云作为镜像服务器
打开containerd配置文件
vi /etc/containerd/config.toml
在文件中加入以下结点:
注意,如果文件中有相同的结点,将
sandbox_image
附加至下面即可,不要创建重复结点。
version = 2
[plugins]
[plugins."io.containerd.grpc.v1.cri"]
sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.9"
网络插件是为集群提供网络实现的部件。
因为某些网络插件需要在初始化时指定cidr网段,因此初始化前你需要决定使用哪个插件。
常用的网络插件有:calico、flannel、weave
并不是所有网络插件都适用于你的网络环境。
SSL alert number 40
)总结:
我想说的是:如果你(我)折腾一个网络插件很久,重装多很多次都不行,也有可能是该插件本身不适用于你的网络环境。不妨换个试试。
使用适当的参数初始化kubernetes:
--pod-network-cidr
是设置后面使用的网络插件的网段,请按照以下说明填写默认网段。
192.168.0.0/16
10.244.0.0/16
--image-repository
: 使用阿里云镜像
k8s.gcr.io
需要填写。--apiserver-advertise-address
: 指定API Server的监听地址。
指令示意:
kubeadm init \
--pod-network-cidr=<网段> \
--image-repository=registry.aliyuncs.com/google_containers \
--apiserver-advertise-address=<公网IP>
在上一步顺利完成后,会显示以下信息:
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
......
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join <ip-address>:6443 --token nrlc17.k0ypuceqs0nmv6i2 \
--discovery-token-ca-cert-hash sha256:c8fe4911959673b6392f46abd89d744de86584225202396cd5f13aec76be53b0
然而无论你是否为root用户,都请按照这个提示启动kubernetes集群:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
而且请记住最后输出的加入token,workers需要使用这个加入集群。(如果没记住也不慌,后文教你重新生成)
验证状态:
kubectl cluster-info
Kubernetes control plane is running at https://<ip-address>:6443
CoreDNS is running at https://<ip-address>:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
观察结点状态:
kubectl get node
NAME STATUS ROLES AGE VERSION
master-1 NotReady control-plane 4m46s v1.28.3
此处NoReady
是正常现象,因为我们还没安装网络插件
恭喜你已经成功渡过第一阶段,你还好吗?
接下来需要进行kubernetes内部的配置,在此之前我需要做一些提醒:
在接下来的过程中,由于环境问题你可能会出现各种各样的状态异常、容器Crash。本文不可能涵盖所有的情况,但我会给你解决问题的方向。
出现这种问题是你应该:
kubectl get pods -A -o wide
等命令查看出错的容器。
kubectl describe pod -n
查看错误的信息kubectl logs -n 查看容器日志
因为下一步“安装网络插件”对环境是破坏性的。如果安装失败了,它很难简单使用kubeadm reset
重置。它会给你的机器引入永久性的改变……
我想说的是,如果网络插件安装失败、或者想改变使用的网络插件,你可能会陷入一种“无论如何配置都不行”的境地。
你仍然可以反复尝试,但我需要提醒的是:如果你多次尝试都失败,很可能是机器环境已经被网络插件改变过了,你可能需要回滚这些设置。
所以:
下面的步骤我们需要拉取各种容器镜像。
由于部分镜像需要在registry.k8s.io
或quay.io
下载。然而这几个源在天朝强大的防火墙下已经无法访问了。
不同于hub.docker.com
,这些网站是无法通过docker配置镜像解决的……
得益于此,要拉取镜像,你需要化简为繁:
registry.k8s.io/xxx...
ImagePullPolicy
修改成Always
以外的值,使其使用本地镜像至此,我是完全投降了……
虽然不是不能做,而是实在太麻烦了!!!
以后还有其它需要registry.k8s.io/xxx...
的容器怎么办,又重复这四步吗???
我的建议是,收手吧阿祖,外面全是防火墙
如果没有魔法,我建议你选一个只在hub.docker.com
拉镜像的方案
因此,国内Worker机器的部署请自求多福,并没有一劳永逸的做法,这个东西会非常麻烦
下面的操作如果涉及内陆无法下载的源,我会尽量提醒
好了,该说的就这么多了,祝你好运!
这一步只需要在Master进行。你只需要选择其中一个安装
你需要安装operator和calico本身。
**注意:**如果安装步骤让你 taint nodes
。这一步是可选的。执行该命令后将允许pod被分配到Master中,一般不建议这么做。建议跳过这句。
请按照官方指引进行安装
本节介绍安装flannel。
如果你不需要进行额外配置,直接下载部署即可:
kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
如果需要改变默认配置,你可以先wget下来,修改后再apply。
安装weave通常也只需要apply一个文件。
类似于……
https://github.com/weaveworks/weave/releases/download/x-x-x/weave-daemonset-k8s.yaml
由于版本号可能会改变,请前往官网获取最新的地址
首先等待所有pod安装完毕
watch kubectl get pods -A -o wide
按ctrl+c
退出
然后执行以下命令验证node准备完毕:
kubectl get nodes
NAME STATUS ROLES AGE VERSION
master-1 Ready control-plane 40m v1.28.3
这一步只需要在每个Worker进行
如果你没有记录连接串,或者连接串已过期,可以在Master结点使用以下命令创建连接串:
kubeadm token create --print-join-command
使用生成的join命令加入集群:
kubeadm join <ip-address>:6443 --token zuyxod.5yglqucae2hejoqj --discovery-token-ca-cert-hash sha256:ff5ab3bcc2eb8aa9b4fb17eee028359fce1799984282cca01d4960a3a84369ce
watch kubectl get node,pod -A -o wide
直到所有pod为Running
,所有node为Ready
该步验证你的Worker可以使用到dns解析
**注意:**本例只保证“某个Worker能够使用CoreDNS”,即CoreDNS基本正常工作;但不代表CoreDNS在所有Worker、Master都正常工作。
如果你想验证后者,请在此基础上进行更多的验证。
查看目前所有的service:
kubectl get svc -A
NAMESPACE NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 50m
kube-system kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 50m
在某个Worker中启动busybox:1.28
(不能使用更高版本镜像):
kubectl run -it --rm --image=busybox:1.28 --restart=Never -- bash
在该pod中,尝试nslookup
所有服务,比如:
nslookup kubernetes.default
nslookup kube-dns.kube-system
如果输出大致如下,则说明该Worker可以连接DNS服务器:
Server: 10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local
Name: kubernetes.default
Address 1: 10.96.0.1 kubernetes.default.svc.cluster.local
如果输出无法解析,请参考官方文档进行DNS排错
确保不存在问题,再进行下一步;如果问题实在不能解决,请考虑更换网络插件
如果你的应用需要存储状态(使用数据库等)需要执行
Kubernetes的持久存储卷 (Persistent Volume,下简称PV) 可以大致分为两类:
一般使用网络存储,因为它与pod所在的node无关。无论pod被部署到哪个结点,它都能访问到位于网络的持久存储卷。
但是如果你的应用需要高强度IO,你可能需要使用本地存储。Kubernetes本地存储插件主要有两个,生产环境中请使用local
而非hostPath
。
local
虽然比hostPath
更好,但也有明显的缺点:
所以请权衡性能与高可用性。
对于内网环境中,一般情况下使用网络存储并不会有明显的IO瓶颈。因此本文配置网络存储。
存储冗余可以保证数据不会丢失。
冗余可以产生在两个层面:
在存储层进行冗余并不是没有缺点,它会导致占用的存储空间成倍增长。
而且存储层的冗余并不能带来数据的高可用性。因为如果你只有一个数据库实例,在这个数据库宕机时,服务仍然无法访问(当然数据是不会丢失)。
所以如果你打算为高可用而组建分布式数据库,存在多个数据库实例,其实数据库本身就给你产生了冗余。此时在底层再次冗余只是浪费空间。
对PV而言,本节主要讨论你是否需要在PV层面进行冗余。
现在,假设你的数据非常宝贵,你不希望丢失数据。
你打算将数据存储到自己的服务器中,而且你至少存在两个Worker,否则白搭。
云原生存储是专为容器环境打造的存储方案。在Kubernetes中,推荐使用云原生存储,而非直接操作文件系统。
云原生存储带来的好处是:
目前比较火的有这些:
选一个用吧,我这里提供OpenEBS和Longhorn的安装方法
请按照官方文档安装longhorn
主要进行两步:
等待所有容器安装完毕:
watch kubectl get pods -n longhorn-system
longhorn会为你添加一个默认的存储类,输入以下命令查看
kubectl get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
longhorn (default) driver.longhorn.io Delete Immediate true 2m12s
这个存储类会默认存储3份冗余,如果这是你想要的,可以跳过。
如果不是,请自行设置默认存储类
首先从github中下载storage class的模板
curl -o longhorn-sc.yaml https://raw.githubusercontent.com/longhorn/longhorn/master/examples/storageclass.yaml
打开,修改模板:
metadata.name
为你喜欢的名称numberOfReplicas:
修改为你所需的数量,这决定冗余存储的份数应用这个存储类
kubectl apply -f longhorn-sc.yaml
确认该存储类正确创建
kubectl get sc
输出类似以下:
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
longhorn (default) driver.longhorn.io Delete Immediate true 9h
my-longhorn driver.longhorn.io Delete Immediate true 1s
需要借助ingress,请在后文配置好ingress访问后,按照官方文档操作。
**注意:**OpenEBS的部分镜像源无法在内陆访问,请自行权衡
我选择安装OpenEBS,当然你可以选择其它的
这一步需要在每个需要OpenEBS分配空间的机器上执行
如果你使用默认的配置安装,那OpenEBS会在所有Worker上分配
OpenEBS需要iSCSI支持,这个需要安装在系统上,不同系统的安装方法不一,可参考这里
在debian中,你可以使用以下命令检测iSCSI是否启动:
systemctl status iscsid
如果找到服务,并且启动,你可以跳到下一步
如果找到服务,但已关闭,请启动:
systemctl enable --now iscsid
如果没找到服务,请安装:
apt-get install open-iscsi
systemctl enable --now iscsid
最后,检测服务确实正常运行:
systemctl status iscsid
按官网指示安装OpenEBS Operator
以及需要的存储支持
OpenEBS提供两种存储方案:
首先查看默认的安装给你装了什么?
kubectl get pods -n openebs -o wide | grep operator
如果没出现你想要的engine,你需要自己安装:
两种方案均有多种存储引擎可供选择,你可以根据自己的需求安装。
比如,你需要使用远程存储,你可以安装cStor
,Jiva
,Mayastor
中的一个。
我这里安装Jiva作为远程存储引擎
安装的具体步骤请参考官网指示
主要做三个事情:
提醒:创建完Policy和Storage Class记得apply
kubectl apply -f <jiva-policy>
kubectl apply -f <jiva-storage-class>
最后,检测storage class正确创建:
kubectl get sc
输出应该存在刚刚创建的storage class:
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
openebs-device openebs.io/local Delete WaitForFirstConsumer false 3h46m
openebs-hostpath openebs.io/local Delete WaitForFirstConsumer false 3h46m
openebs-jiva-csi-sc jiva.csi.openebs.io Delete Immediate true 6s
由于Jiva Storage Class是支持动态提供(Dynamic Provisioning)的,因此我们不需要手动创建PV
设置默认存储类可以使其它应用在不指明存储类的时候也能使用持久存储。非常建议为集群设置一个默认存储类。
但这并不是必须的
默认存储类会在kubectl get sc
的输出中显示default
字样
首先我们查看所有存储类
kubectl get sc
如果你发现以下情况,建议往下执行:
我们可以使用以下指令设置/取消一个默认存储类:
kubectl patch storageclass <storage-class-name> -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
注意
填写存储类的名字;最后的布尔值控制是设置还是取消。
设置后再次检测storage class的情况,输出应如下。 请确保至多只有1个默认存储:
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
openebs-device openebs.io/local Delete WaitForFirstConsumer false 3h54m
openebs-hostpath openebs.io/local Delete WaitForFirstConsumer false 3h54m
openebs-jiva-csi-sc (default) jiva.csi.openebs.io Delete Immediate true 8m30s
如果你需要支持公网访问,你需要进行这一步
本节将使用ingress nginx controller配置公网访问。
安装ingress非常简单,根据官方教程,使用deployment安装:
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.2/deploy/static/provider/cloud/deploy.yaml
输入以下命令等待容器创建完毕
watch kubectl get pods -n ingress-nginx
最后你会看到类似这样的结果,只要看到controller为Running
就是正常:
NAME READY STATUS RESTARTS AGE
ingress-nginx-admission-create-6vlrc 0/1 Completed 0 5m12s
ingress-nginx-admission-patch-7wvqp 0/1 Completed 1 5m12s
ingress-nginx-controller-8558859656-zskdq 1/1 Running 0 5m12s
此时查看支持ingress正常运作的LoadBalancer服务:
kubectl get svc -n ingress-nginx
你会发现输出如下,EXTERNAL-IP
永远为pending
:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller LoadBalancer 10.111.15.62 <pending> 80:32503/TCP,443:30116/TCP 7m18s
ingress-nginx-controller-admission ClusterIP 10.97.192.44 <none> 443/TCP 7m18s
随之你会发现ingress nginx controller无法外部访问……
这是因为自建Kubernetes与云环境不同:自建集群并不自带负载均衡器实现,如果你此时创建LoadBalancer
,将永远处于pending
状态。
对此我们有两种做法:
下面将介绍这两种做法,注意,并不是所有做法都适合你的情况,请注意阅读后续提及的先决条件和弊端。
**注意:**总共有3种做法,选择1种执行即可。
这些做法出自ingress nginx官方文档
裸机配置首选!!!
该方法只适合所有结点(至少是所有Worker结点)处于同一内网。
也就是:硬件裸机,或者某些支持组内网的云服务商。(但我发现某些国外的vps商若处于同一机房也能用)
首先,请按照官方指南安装metallb
然后,配置IP池。最简单且内网通用的做法是使用Layer 2(数据链路)模式
你只需要将你的公网IP段加入IP池就好。
简单来说就是把你希望作为外网访问入口的IP段加入到IP池,MetalLB会将这些IP依次分配给出现的LoadBalancer
网段支持子网写法和范围写法
如果你的服务器只有单个IP,可以视为只有单个IP的子网
写法示意如下:
addresses:
- 123.123.10.0/24
- 123.123.9.1-123.123.9.5
- fc00:f853:0ccd:e799::/124
- 123.123.11.10/32
由于LoadBalancer是交通枢纽。如果你的服务器各自有流量限制,请尽量选择流量充足的服务器写进IP池。
因为MetalLB版本迭代非常快,因此这里也不放具体的配置了,请按照官方指南进行配置。
错误排查
你可能会遇到webhook错误,请尝试将MetalLB的Controller转移到Master结点。
错误原因不明,详情请参考这个issue。
执行结束后,输入以下命令可以查看nginx ingress的LoadBalancer IP:
kubectl get svc -n ingress-nginx
如无意外,此时LoadBalancer显示的将是一个公网IP。
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx-controller LoadBalancer 10.111.15.62 <Public-IP> 80:32503/TCP,443:30116/TCP 21m
ingress-nginx-controller-admission ClusterIP 10.97.192.44 <none> 443/TCP 21m
效仿云服务,我们也可以自己整一个外部负载均衡器。这个负载均衡器可以是硬件或软件。
软件负载均衡器,推荐使用HAProxy
但这个方法我没试,看起来非常专业,有兴趣的朋友可以配置一下
我们也可以不使用任何LoadBalancer,ingress nginx controller提供了直接对外访问的做法。
首先我们将部署文件下载下来:
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.2/deploy/static/provider/cloud/deploy.yaml
在里面找到kind: Deployment
的项,加入以下配置项(注意不要引入重复的项):
template:
spec:
hostNetwork: true
保存退出后,将其应用:
kubectl apply -f deploy.yaml
此时检查nginx controller的情况:
kubectl get pods -n ingress-nginx -o wide
你会发现nginx controller的IP变成了pod所在node的公网IP(前提是你的node真的有公网IP)
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
ingress-nginx-admission-create-6vlrc 0/1 Completed 0 140m 10.244.7.11 rn-l-3500m7t <none> <none>
ingress-nginx-admission-patch-7wvqp 0/1 Completed 1 140m 10.244.6.13 rn-m-2g4t <none> <none>
ingress-nginx-controller-7f8dd58d99-s9qmg 1/1 Running 0 50s <public-ip> rn-m-2g4t <none> <none>
注意事项:
那么怎么指定访问nginx的公网IP呢?
只能间接指定,有两个做法:
做法1:使用结点选择/亲和性配置,让nginx controller优先创建于你指定的node
首先为希望运行ingress的node创建一个type
为ingress
的标签(你可以更改为任意的键值对)
kubectl label nodes <name_of_your_node> type=ingress
在部署nginx controller前,修改Deployment
在里面找到kind: Deployment
的项,加入以下配置项(注意不要引入重复的项):
template:
spec:
nodeSelector:
type: ingress
修改完后重新apply
你可能需要将现有的ingress-nginx-controller pod删除以触发重新调度
做法2:使用daemon set部署nginx controller,让每个node(包括Master)都运行nginx controller
使用上步暴露的公网IP(各个做法不同),在外部浏览器中尝试进行访问。
如果显示nginx 404
页面,说明配置正确。
恭喜,到这一步你已经配置好生产环境下使用的Kubernetes了
接下来你只需要:
spec.rules.host
;如果使用域名访问,请务必指明非必须,单如果是公开访问的应用,建议进行
这一步你需要准备:
首先将证书内容复制到服务器,比如我的:
root@master-1:~/cert# ls
mysite.com.crt mysite.com.key
创建一个包含证书内容的secret
kubectl create secret tls <your-secret-name> --cert=mysite.com.crt --key=mysite.com.key
修改你的ingress(nginx)部署文件,加入以下结点:
spec:
tls:
- hosts:
- mysite.com
secretName: your-secret-name # 这个是上步的secret名称
rules:
- host: mysite.com # 站点名必须对应,否则返回404
重新apply
使用https://mysite.com
访问你的站点,确认TLS证书已生效
大功告成!至此我们终于成功自建了Kubernetes网络
这一路上并不容易,但这仅仅只是一个开始
你还需要关注如何进行维护、备份和迁移……
但到此我有一个疑问
Docker、Kubernetes的出现不是为了简化应用部署的过程吗?
但搞起来怎么这么复杂呢?
程序员的工作是降低了,但运维真就哭了……
但无所谓,反正我这种oneman从来都是一个人全部搞定,四舍五入没节省任何时间
好吧,牢骚是发到这……
其实Kubernetes部署到部分云服务商还是很舒服的,只是我看到那个价格就已经饱了
所以自建Kubernetes虽然能达到生产环境的要求,但需要额外的维护!
除非你真的有充分的理由,否则云服务商还是一个不错的选择啊(除了很贵)