伴随着开源项目lab-k8s-playground v1.2的发布,All-in-One K8S Playground现在可以同时支持标准Kubernetes和OpenShift啦!本文总结了在支持OpenShift v3.11过程中遇到的一系列问题。如果您喜欢这个项目,欢迎点击下面的按钮,关注,加星,以及贡献代码^_^
OpenShift
OpenShift是Red Hat开发的构筑于Kubernetes之上的企业级容器应用平台,为企业应用与服务的开发,管理,以及部署提供了全面的支持,是当前炙手可热的一款Kubernetes发行版本。其社区版称为OKD(OpenShift Kubernetes Distribution的缩写,原名Origin)。
在All-in-One K8S Playground新增OpenShift支持一文中,我们已经了解了,如何利用All-in-One Kubernetes Playground在单机环境下部署一个支持OKD v3.11版本的单节点集群,以及如何在上面部署Istio和API Connect。
本文将告诉你,All-in-One K8S Playground在支持OpenShift v3.11过程中遇到的一些问题,以及相应的解决办法。这其中,大部分问题的解决办法都已经通过脚本的形式固化在了All-in-One K8S Playground里,这也是该Playground的价值所在!
坑#1:Web Console登录总是重定向到127.0.0.1
在本机启动OpenShift集群时,服务器的访问地址基本都是127.0.0.1
。但有时候,我们也会在远程机器上部署OpenShift集群,这个时候的服务器访问地址通常就是某个具体的IP地址或者hostname了。
在利用oc cluster up
命令启动OpenShift的时候,OpenShift为我们提供了一个参数--public-hostname
,用来指定集群启动起来以后服务器的访问地址。比如:
$ oc cluster up --public-hostname=$HOST_IP
但即便如此,我们也经常会遇到OpenShift在登录Web Console时自动重定向到127.0.0.1
这样的情况。这往往是由于,我们在上一次启动OpenShift时使用了127.0.0.1
,而在本次启动OpenShift时又没有清除之前启动时留在本地的配置文件目录。这个时候,可以先清除本地OpenShift的配置文件目录,然后再启动OpenShift。
在Playground里,配置文件目录在
~/openshift.local.clusterup
下,执行launch kubernetes::clean
时会为我们清除掉这个目录。
有关这一问题的详细讨论,参见:
网络资源 |
---|
Access fail with ‘oc cluster up –public-hostname=public ip’ and redirect to 127.0.0.1 |
坑#2:Admission Webhook默认没有开启
在部署类似Istio这样的应用时,需要我们的Kubernetes集群开启Admission Webhook。Kubernetes从v1.11开始默认就开启了这项功能。但是,OpenShift直到v3.11为止,默认都还没有开启它。
事实上,OpenShift的GitHub库里是有专门的PR用来解决这一问题的。但是由于种种原因,最后并没有进入v3.11。
在v3.11上解决这一问题的方法,可以参考Minishift的这个PR。
在Playground里,执行
launch istio
时,会自动完成对OpenShift配置的修改以开启Admission Webhook,并自动重启OpenShift的API服务,以使配置修改生效。
有关这一问题的详细讨论,参见:
网络资源 |
---|
Consider enabling admission webhooks by default with oc cluster up |
Enable mutating and validating webhooks |
坑#3:API服务重启后不能立刻对外提供服务
为了启动Admission Webhook,我们需要对OpenShift的配置进行修改,并重启它的API服务。关于重启API服务的方法,可以参考Minishift的这个PR。
做为自动化脚本的一部分,我们需要在检测到API服务成功重启以后,继续后面的部署工作。为此,参照Minishift的做法,我们可以通过访问/healthz
来判断OpenShift的API服务是否已经成功启动:
$ curl -k https://$HOST_IP:8443/healthz
通常,当/healthz
返回ok
的时候,就表示API服务可以对外提供服务了。但是,在实际测试的过程中发现,即使/healthz
返回ok
,某些OpenShift的操作仍然会失败。比如:
$ oc login -u system:admin
Error from server (InternalError): Internal error occurred: unexpected response: 400
在Playground里,当重启API服务时,除了检测
/healthz
,还增加了额外的检测机制,以保证重启后的API服务能够真正对外提供服务。
有关这一问题的详细讨论,参见:
网络资源 |
---|
How to detect if apiserver is fully restarted and ready for use |
坑#4:HostPath PV报Permission denied
部署API Connect时,我们使用了HostPath类型的Persistent Volume。但很多Pod在启动过程中都会遇到创建目录或文件失败的情况,从而导致Pod启动失败。比如:
$ klo r31f4a26f5e-apiconnect-cc-0 -n apiconnect
mkdir: cannot create directory '/var/db/data': Permission denied
mkdir: cannot create directory '/var/db/logs': Permission denied
这是因为大多数API Connect的Pod都以非root用户运行,而在宿主机上创建的Persistent Volume目录,默认权限都是drwxr-xr-x
,即:group
和other
对目录都没有写的权限,导致Pod在这些目录下无法创建子目录或文件。
根据实际测试,除了按照API Connect的文档,把anyuid
这个Security Context Constraint赋给apiconnect
名字空间下的所有service account之外:
$ oc adm policy add-scc-to-group anyuid system:serviceaccounts:apiconnect
我们还需要为Persistent Volume目录及其子目录和文件赋予更大的权限:
$ chmod ugo+rwx -R /path/to/apic/pv
在Playground里,
launch apic
会帮我们自动创建API Connect运行所需的Persistent Volume目录及其子目录,并为它们赋予足够的权限。
有关这一问题的详细讨论,参见:
网络资源 |
---|
Directories provisioned by hostPath provisioner are only writeable by root |
Permission denied in pod |
OpenShift: insufficient permission inside the containers |
坑#5:OpenShift的DNS服务问题
API Connect在运行期间需要通过指定的域名来访问它所提供的服务,这就要用到DNS服务了。标准的Kubernetes从v1.13开始就默认使用CoreDNS来替代原来的Kube-DNS实现了。基于CoreDNS,我们可以利用它的hosts插件为API Connect指定静态DNS规则,就像在/etc/hosts
里配置IP-Host
映射一样。
而OpenShift的DNS服务,到v3.11为止,一直都是基于一个叫做SkyDNS的项目实现的。通过尝试发现,它并没有提供类似CoreDNS的hosts插件那样的方法对DNS进行定制。因此,我们需要为OpenShift配置额外的DNS服务器,甚至可能要搭建自己的DNS服务器。对于只是配置静态DNS规则这样的简单需求而言,这个方案就有点过于复杂了。
目前,Playground采用的解决办法是基于nip.io的公共DNS服务,实现域名到IP的自动转换。事实上,OpenShift通过route定义暴露集群服务默认也是用的nip.io。
根据OpenShift 4.1的Release Notes,似乎从v4.x开始,OpenShift用CoreDNS取代了原来的SkyDNS。从相应的PR里可以看到,所有和SkyDNS相关的逻辑也都被清除掉了。
有关这一问题的详细讨论,参见:
网络资源 |
---|
What’s the simplest way to setup IP host mappings for OpenShift … cluster? |
Why OKD 3.11 with Kubernetes 1.11,but not use CoreDNS? |
坑#6:openshift.local.volumes目录删除失败
当我们用oc cluster down
把OpenShift集群停掉时,有时也希望把OpenShift留在本地的配置文件目录一并删除掉。但在CentOS和RHEL上,删除这个目录时会报错:
$ rm -rf ~/openshift.local.clusterup
rm: cannot remove ‘openshift.local.clusterup/openshift.local.volumes/pods/916be4fd-e32f-11e9-b688-005056bcdc55/volumes/kubernetes.io~secret/serving-cert’: Device or resource busy
...
这是由于OpenShift集群在运行期间会为Pod在宿主机上设置mount点,而停掉集群的时候,这些mount点由于某些原因,并没有被正确地unmount。解决这一问题的方法是手工对它们进行unmount,具体做法可以参考这个PR。
在Playground里,执行
launch kubernetes::clean
时会自动帮我们寻找当前还没有被unmount的与OpenShift有关的目录,并逐一执行unmount。
有关这一问题的详细讨论,参见:
网络资源 |
---|
Umount secret volumes before trying to remove |
坑#7:Docker Desktop在Mac上的代理问题
在Mac上启动Openshift时,会在集群启动结束时见到下面的警告信息:
WARNING: An HTTP proxy (gateway.docker.internal:3128) is configured for the Docker daemon, but you did not specify one for cluster up
WARNING: An HTTPS proxy (gateway.docker.internal:3129) is configured for the Docker daemon, but you did not specify one for cluster up
WARNING: A proxy is configured for Docker, however 172.30.1.1 is not included in its NO_PROXY list.
172.30.1.1 needs to be included in the Docker daemon's NO_PROXY environment variable so pushes to the local OpenShift registry can succeed.
这是由于Docker Desktop for Mac从某个版本开始引入了一种内部代理机制,叫做“transparent proxy”。如果执行docker info
命令,我们可以看到,HTTP Proxy
和HTTPS Proxy
这两项被设置成了相应的值:
$ docker info|grep -i proxy
HTTP Proxy: gateway.docker.internal:3128
HTTPS Proxy: gateway.docker.internal:3129
即便运行Docker时不需要代理,这两个值也是始终存在的。OpenShift在启动时提供了相应的命令行参数:--http-proxy
,--https-proxy
,可以帮我们把这两个值传给OpenShift。
另一方面,做为OpenShift的内部Docker Registry,IP地址为172.30.1.11
,是不需要经过代理的,因此它应该出现在NO_PROXY
环境变量里。
但问题是,我们通过Docker Desktop提供的界面对NO_PROXY
的设置并不起作用(Preferences… > Proxies > Manual proxy configuration > Bypass proxy settings for these hosts & domains)。
目前为止,Docker Desktop的最新版本还没有修复这个问题。不过,据称它的17.09.1-ce-mac42版本是可以工作的。因此,现在解决这一问题的唯一方法是安装低版本的Docker Desktop。
有关这一问题的详细讨论,参见:
坑#8:/var/lib/kubelet/device-plugins问题
在Mac上启动OpenShift还会遇到下面的错误,导致集群启动失败:
Mounts denied: The path /var/lib/kubelet/device-plugins is not shared from OS X and is not known to Docker. You can configure shared paths from Docker -> Preferences... -> File Sharing. See https://docs.docker.com/docker-for-mac/osxfs/#namespaces for more info.
一种解决办法,是通过Docker Desktop for Mac的Preferences界面,先把Kubernetes开启,然后再把它关闭:Preferences… > Kubernetes > Enable Kubernetes。
有关这一问题的详细讨论,参见:
网络资源 |
---|
openshift v3.11 does not start on Mac OS X |
坑#9:OpenShift集群在Mac上重启失败
这个问题同样是和Mac相关的,当我们在先前已经成功启动过OpenShift集群的Mac机器上再次启动OpenShift时,会遇到因为端口被占用的错误而导致重启失败:
Getting a Docker client ...
Checking if image openshift/origin-control-plane:v3.11 is available ...
Checking type of volume mount ...
Determining server IP ...
Checking if OpenShift is already running ...
Checking for supported Docker version (=>1.22) ...
Checking if insecured registry is configured properly in Docker ...
Checking if required ports are available ...
error: a port needed by OpenShift is not available
这是由于,Docker Desktop默认会把Kubernetes相关的系统级Docker容器隐藏起来,包括:那些k8s_POD_
打头的容器,以及kube_system
名字空间下的容器,它们用docker ps
是查不到的。
另一方面,oc cluster down
在执行时由于获取不到这些系统级容器,所以也就无法停掉它们。OpenShift集群运行所需要的端口,就是被这些容器占用的。利用lsof
命令可以看到,具体的端口包括1936
,443
,80
:
$ lsof -Pni|grep com.docke.*TCP.*LISTEN
com.docke 45430 moyingbj 7u IPv4 0x6dcd0b5b57f496b1 0t0 TCP 127.0.0.1:56861 (LISTEN)
com.docke 45434 moyingbj 15u IPv6 0x6dcd0b5b2df9e889 0t0 TCP *:1936 (LISTEN)
com.docke 45434 moyingbj 17u IPv6 0x6dcd0b5b3066f2c9 0t0 TCP *:443 (LISTEN)
com.docke 45434 moyingbj 20u IPv6 0x6dcd0b5b3066ed09 0t0 TCP *:80 (LISTEN)
解决的办法同样是通过Docker Desktop for Mac的Preferences界面,首先开启Kubernetes,然后确保勾选了“Show system containers (advanced)”,最后再关闭Kubernetes。
有关这一问题的详细讨论,参见:
网络资源 |
---|
error: a port needed by OpenShift is not available |
oc cluster down leave hypershift process running when using docker for mac |
更多参考资料
读到这里,相信你对开源项目lab-k8s-playground及其All-in-One Playground的应用应该有了更全面的了解了。那么,还有哪些参考资料你可以访问呢?那就请快速读一下下面这段Shell脚本编写的“代码”吧😊 相信一定难不倒你!
选择你感兴趣的分支,点击相应分支下列出的文档资源。最后,如果您喜欢这个项目,欢迎点击本文开头处(或下列代码注释里)的按钮,关注,加星,以及贡献代码^_^
function where_to_start {
case $I_want in
"to learn what it provides in general")
cat "All-in-One K8S Playground Overview"
;;
"to get started quickly")
cat "All-in-One K8S Playground Usage Guide"
cat "All-in-One K8S Playground 中文使用指南"
;;
"to understand what's behind")
cat "Launch multi-node k8s cluster locally in one min..."
cat "Kubernetes实战视频: 如何1分钟内在本地启动一个多节点集群"
cat "OpenShift v3的填坑之旅"
cat "OpenShift v4的填坑之旅"
;;
"to extend it by myself")
cat "Launch Utility Usage Guide"
cat "A Sample Target for Demo Purpose"
;;
"to learn more cool features")
cat "Quick Guide to Launch APIC Playground"
cat "把API Connect关进All-in-One K8S Playground里"
cat "All-in-One K8S Playground新增OpenShift支持"
cat "All-in-One K8S Playground支持OpenShift v4"
;;
"to contribute back")
# Feel free to click these buttons: Watch Star Fork
git clone https://github.com/morningspace/lab-k8s-playground.git
;;
esac
}
留下评论
您的电子邮箱地址并不会被展示。请填写标记为必须的字段。 *