引言

最近做边缘计算项目,因为没有基础,所以首先学习Kubernetes。感觉系统的中文入门资料比较少,只找到《Kubernetes权威指南》(龚正、吴治辉等著,下称《指南》),照着第一章的demo教程编写,前前后后遇到不少问题,也是找了好多资料才解决。所以从头写一下如何配置一个单机版MySQL+Tomcat的demo,希望能给陷入同样困境的同学一点帮助。

文章较长,如果你已经按照《指南》的demo走了一遍,但是遇到了问题,可以直接看最后的“坑点总结”中的解决方案能否解决你的问题。

知识准备和环境准备

前导知识

本着对零基础的同学友好的态度,前排提示阅读本文前你至少需要以下知识:

  1. 掌握虚拟机的使用,尤其是网络的配置
  2. Linux的使用,尤其是CentOS 7的systemctl功能
  3. 了解如何更换软件安装源(主要是yum和docker)
  4. 了解docker和容器的基本概念
  5. 大致了解yaml
  6. 可能的kexue上网方法(但一般可以通过更换软件源代替)

也就是说,以上的知识本文不会详细展开。如果其中有读者从来没有听说过的概念,最好先学习一下。

实验环境

笔者的实验环境:

Win10 + VMWare14中安装CentOS 7(带GUI),桥接模式上网

之所以强调是CentOS 7(包括RHEL 7),是因为它的系统服务配置使用的是systemctl命令,这可能与其他CentOS版本或Linux发行版有所不同。当然,如果你对Linux的系统服务配置有经验,可以不采用和笔者相同的版本。

另外,下面所有操作最好在root下进行,避免出现权限不足的问题。

Kubernetes安装和配置

基本上按照《指南》中的环境准备如下:

关闭防火墙

终端输入以下命令关闭防火墙:

systemctl disable firewalld  #禁止防火墙开机启动
systemctl stop firewalld #关闭防火墙服务

如果tab之后有后缀.service是一样的,不带后缀的是简称。

可以使用下面的命令查看防火墙是否已经关闭,如果是inactive表明已关闭:

systemctl status firewalld

当然,生产环境需要自己配置端口访问控制,不能完全关闭防火墙。这里因为是较安全的内网,学习和测试用,直接关闭比较方便。

安装etcd和Kubernetes

yum install -y etcd kubernetes

kubernetes的每个组件有各自的配置文件,可以自定义。而该命令会执行默认配置的安装,对kubernetes尚不了解时一键安装非常方便。

如果安装缓慢,可以尝试更换国内的yum安装源,或者代理上网(虚拟机可以共享物理机的代理端口,SSR和clash软件都有允许局域网共享的功能)。

修改配置文件

此处需要修改两处配置文件。

  • Docker配置文件

Docker配置文件为/etc/sysconfig/docker,将OPTIONS的内容设置为:

OPTIONS='--selinux-enabled=false --insecure-registry gcr.io'

可以注释OPTIONS所在行,而非删除它,以留出容错空间ω

  • Kubernetes apiserver配置文件

Kubernetes apiserver配置文件为/etc/kubernetes/apiserver,将--admission_control参数中的ServiceAccount删除(同样地,可以注释原行,复制一行来修改)。也就是更改为:

KUBE_ADMISSION_CONTROL="--admission-control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ResourceQuota"

也许你的--admission_control参数并不是在KUBE_ADMISSION_CONTROL变量下,但是在哪里其实是一样的,只要之后的变量读取都有录入即可(不细讲,笔者也尚未完全学习),这里只需要删除。

启动kubernetes服务

按顺序启动以下服务:

systemctl start etcd
systemctl start docker
systemctl start kube-apiserver
systemctl start kube-controller-manager
systemctl start kube-scheduler
systemctl start kubelet
systemctl start kube-proxy

至于为什么要按顺序,笔者认为是因为后面的服务对前面的有依赖,启动顺序不对可能会导致某些意外错误。

这里有一个坑点,就是kube-apiserver启动时必须要开启网络连接,否则会报错:

Job for kube-apiserver.service failed because the control process exited with error code. See "systemctl status kube-apiserver.service" and "journalctl -xe" for details.

因为笔者系统是带GUI的,直接在右上角设置网络连接即可。如果是纯字符界面可能需要自己开启网络服务。

另外,将start选项改为stop和restart分别是停止服务和重启服务,改为enable表示加入开机启动列表。

一键启动脚本

因为是学习阶段,出现各种错误老是需要开开关关,所以写了一个一键启动的脚本。

创建service-list.txt文件,按顺序写上所有需要启动的服务名称:

etcd
docker
kube-apiserver
kube-controller-manager
kube-scheduler
kubelet
kube-proxy

创建脚本文件k8s-service-start.sh:

#!/bin/bash
for SERVNAME in `cat service-list.txt`
do
systemctl status $SERVNAME &> /dev/null
if [ $? -eq 0 ]
then
echo "Already Active : $SERVNAME"
else
systemctl start $SERVNAME
systemctl status $SERVNAME &> /dev/null
if [ $? -eq 0 ]
then
echo "Start Success : $SERVNAME"
else
echo "! Start fail : $SERVNAME"
fi
fi
done

记得给脚本加上执行权限:

chmod +x k8s-service-start.sh

当然,如果已经使用systemctl enable加入了开机启动就无需重复操作了。

Docker镜像加速

一般从官方网站下载Docker镜像都比较慢,所以设置一下国内源进行镜像加速。

在/etc/docker/daemon.json 中写入如下内容(如果文件不存在请新建该文件):

{"registry-mirrors":["你的镜像加速地址"]}

我使用的是阿里云源,在阿里云账号的“容器镜像服务 - 镜像中心 - 镜像加速器”菜单中可以找到你专属的镜像加速地址。

你也可以使用其他地址:

网易:https://hub-mirror.c.163.com/

七牛云:https://reg-mirror.qiniu.com

之后重启docker服务:

systemctl daemon-reload
systemctl restart docker

启动MySQL服务

以上都是安装和配置,下面正式进入到kubernetes的使用了。

首先最好新建一个工作文件夹,方便管理。

编写mysql-rc文件

在工作文件夹下新建RC定义文件mysql-rc.yaml,内容如下:

apiVersion: v1
kind: ReplicationController
metadata:
name: mysql
spec:
replicas: 1
selector:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:5.7 #若不加版本号5.7,可能会导致错误
ports:
- containerPort: 3306
env:
- name: MYSQL_ROOT_PASSWORD
value: "123456"

这里yaml文件中的kind属性,用来表示资源对象的类型,比如这里就表示一个RC。(最外层的)spec一节表示RC的相关属性定义,如replicas表示期望实例数量,template是创建POD实例的模板。注意template中的labels必须与前面的selector匹配。

原版书的spec.containers.image没有写版本号,默认拉取latest镜像,这可能会导致一些不兼容的错误。笔者使用5.7版本没有问题。

另外注意缩进要正确。

编写mysql-svc文件

新建Service定义文件mysql-svc.yaml,内容如下:

apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
ports:
- port: 3306
selector:
app: mysql

启动Service和发布RC

文件编写完毕后,就可以启动Service和发布RC了。

  1. 创建Service:
kubectl create -f mysql-svc.yaml
# 正确输出:service "mysql" created

此外对应地,可以用如下命令删除服务:

kubectl delete -f mysql-svc.yaml
  1. 查看Service是否创建成功:
kubectl get svc
# 正确输出:
# NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
# kubernetes 10.254.0.1 <none> 443/TCP 2d
# mysql 10.254.21.86 <none> 3306/TCP 17h

其中CLUSTER-IP是kubernetes为POD自动分配的集群内IP,与宿主机无关(且与宿主机网段不能重合)。

  1. 发布RC:
kubectl create -f mysql-rc.yaml
# 正确输出:replicationcontroller "mysql" created
  1. 查看RC状态:
kubectl get rc
# 正确输出,READY应为1:
# NAME DESIRED CURRENT READY AGE
# mysql 1 1 1 17h

查看POD状态:

kubectl get pods
# 正确输出,READY应为1,STATUS应为Running:
# NAME READY STATUS RESTARTS AGE
# mysql-8811b 1/1 Running 1 17h

如果STATUS为Pending或ContainerCreating,说明还在下载或创建容器,可以等待片刻。如果长时间处于此状态,或者状态变为CrashLoopBackOff或Error,说明出现了某些错误。可以检查一下所有的服务是否已开启,yaml文件编写有无错误(拼写、缩进、多余的空格等)。

读者可能注意到,之前是先编写rc文件再编写svc文件的,但此处是先创建Service再发布RC。实际上,《指南》中是先发布RC再创建Service的,但有博客说这样启动出现了一些问题(虽然不是这个例子),因此这里先创建Service再发布RC。

启动MyWeb服务

上一节定义和启动了MySQL服务,这里用同样的步骤启动Tomcat,也就是Web应用。

编写myweb-rc文件

创建myweb-rc.yaml文件,内容如下:

kind: ReplicationController
metadata:
name: myweb
spec:
replicas: 5
selector:
app: myweb
template:
metadata:
labels:
app: myweb
spec:
containers:
- name: myweb
image: kubeguide/tomcat-app:v1
ports:
- containerPort: 8080
env:
- name: MYSQL_SERVICE_HOST
# value: 'mysql'
value: 10.254.21.86 # 这里很坑,集群尚未启动域名解析服务,需要直接填写mysql服务的IP地址
- name: MYSQL_SERVICE_PORT
value: '3306'

这个文件也很关键,按照《指南》里写可能会出错。坑点是MYSQL_SERVICE_HOST的值要直接写mysql服务的IP地址,也就是之前使用kubectl get svc命令查看到的mysql的IP。

当然,真正应用时一定不会这么做,因为某个POD是有可能挂掉的,下次启动时IP可能就会变。但是在刚刚入门时啥都不懂的情况下,这样做是最快的,否则搞了半天看不到成功结果,是非常打击学习兴趣和信心的(笔者就是QwQ)。

编写myweb-svc文件

创建myweb-svc.yaml文件,内容如下:

apiVersion: v1
kind: Service
metadata:
name: myweb
spec:
type: NodePort
ports:
- port: 8080
nodePort: 30001
selector:
app: myweb

启动Service和发布RC

发布Service:

kubectl create -f myweb-svc.yaml
# 正确输出:service "myweb" created

发布RC:

kubectl create -f myweb-rc.yaml
# 正确输出:replicationcontroller "myweb" created

同样地,可以用kubectl get命令来查看各种资源的状态。

浏览器访问网页

终于到了激动人心的时刻,配置完毕,可以开始访问网站了。

使用物理机的浏览器访问:

http://虚拟机的IP:30001/demo/

如果成功,你会看到如下页面:

点击“Add...”可以增加记录。

如果不能访问,就用虚拟机自己的浏览器来访问。如果虚拟机可以访问,那么很可能是防火墙的问题,需要关闭后重启kubernetes相关服务,再执行命令:

iptables -P FORWARD ACCEPT

如果还是不能解决,也许你要从头开始检查每个步骤,甚至可能遇到笔者未遇到的错误。假如下面一节的方法都不能解决你的问题,那么笔者也无能为力了orz!

Good luck!_

坑点总结

总结一下笔者踩到的坑。当然也不一定就是关键的错误,但下面的方案笔者都试过。

使用下面的命令查看pods的日志,可能有助于定位错误:

kubectl logs POD名

mysql无法链接

现象

可以访问网页,但浏览器显示报错:

Error:com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.

解决方案

有2种可能性:

  1. mysql版本不对。
  2. 无法进行域名解析

对于1,删除mysql的RC资源,将mysql-rc.yaml中的image参数改为mysql:5.7后重新发布。

对于2,将myweb-rc.yaml中MYSQL_SERVICE_HOST的value改为mysql服务的IP地址,也就是用kubectl get svc查看到的地址,重新发布RC。

物理机无法访问网页

现象

物理机无法访问网页,但虚拟机可以。

解决方案

  1. 查看防火墙状态:
systemctl status firewalld
  1. 如果没有关闭则手动关闭:
systemctl disable firewalld  #禁止防火墙开机启动
systemctl stop firewalld #关闭防火墙服务
  1. 重启kubernetes相关服务

  2. 执行以下命令:

iptables -P FORWARD ACCEPT

无法启动kube-apiserver

现象

启动kube-apiserver报错:

Job for kube-apiserver.service failed because the control process exited with error code. See "systemctl status kube-apiserver.service" and "journalctl -xe" for details.

解决方案

首先打开CentOS自己的网络连接,再启动kube-apiserver。

RC状态卡住

现象

RC的状态卡在ContainerCreating/Pending,或变成CrashLoopBackOff/Error。

解决方案

检查rc的yaml文件有无错误,包括拼写、缩进、多余的空格等。

如果文件编写无误,尝试更换Docker国内镜像源或kexue上网。

其他错误

现象

其他报错,或者看不到报错,但虚拟机和物理机都不能访问。

解决方案

按照本文从头检查所有步骤,若仍然有错可以尝试:

  • 删除所有RC和Service,先创建Service,再启动RC
  • 重启所有kubernetes服务
  • 重启虚拟机
  • 打开百度/谷歌/StackOverflow

参考资料:

k8s中部署 Tomcat+MySQL服务

在k8s中定义和启动mysql和tomcat服务之后,浏览器无法访问的问题

Kubernetes单机创建MySQL+Tomcat演示程序:《Kubernetes权威指南》第一章demo报错踩坑的更多相关文章

  1. PADSPCB权威指南-第一章 PADS软件系统(部分)(原创)

    PADSPCB权威指南-第一章(部分)豆丁地址:http://www.docin.com/p-707128286.html

  2. 刚创建的maven项目,pom.xml的第一行就报错

    刚创建的maven项目,马上pom.xml的第一行就报错这是第一行:<project xmlns="http://maven.apache.org/POM/4.0.0" xm ...

  3. Kubernetes权威指南 第一章:Kubernetes入门

    Kubernetes是什么 官网 https://kubernetes.io/ 中文版:https://kubernetes.io/zh/ Kubernetes是谷歌十几年大规模容器管理经验的成果 是 ...

  4. Javascript权威指南——第一章Javascript概述

    示例:javascript贷款计算器 相关技术: 1.如何在文档中查找元素: 2.如何通过表单input元素来获取用户的输入数据: 3.如何通过文档元素来设置HTML内容: 4.如何将数据存储在浏览器 ...

  5. 修改了Mysql密码后连接不到服务且无报错信息解决方法以及修改密码方法

    安装MYSQL后更改了root的密码后用 net start mysql 启动时出现:无法启动,无报错信息 使用以下命令:1.管理员方式cmd进入mysql安装目录的bin目录下2.执行命令:mysq ...

  6. create-react-app 创建的项目执行npm run eject后,运行报错

    create-react-app 创建的项目执行npm run eject后,运行报错:Cannot find module '@babel/plugin-transform-react-jsx-so ...

  7. 【笔记】javascript权威指南-第二章-词法结构

    词法结构 //本书是指:javascript权威指南    //以下内容摘记时间为:2013.7.28   字符集 UTF-8和UTF-16的区别?Unicode和UTF是什么关系?Unicode转义 ...

  8. mysql升级到5.7时间戳(timestamp)默认值报错

    原文:mysql升级到5.7时间戳报错 往数据库里创建新表的时候报错: [Err] 1067 - Invalid default value for 'updateTime' DROP TABLE I ...

  9. 恢复云数据库MySQL的备份文件到自建数据库遇到的报错

    报错信息 : 恢复云数据库MySQL的备份文件到自建数据库,自建数据库版本5.6.36. 按照阿里云文档操作,启动数据库报错 -- :: [ERROR] /application/mysql/bin/ ...

  10. 【MySQL】InnoDB: Error: checksum mismatch in data file 报错

    参考:http://www.jb51.net/article/66951.htm 用5.7版本启动原5.5实例后,再用5.5启动出现以下报错 InnoDB: Error: checksum misma ...

随机推荐

  1. day42-反射01

    Java反射01 1.反射(reflection)机制 1.1反射机制问题 一个需求引出反射 请看下面问题: 根据配置文件 re.properties 指定信息,创建Cat对象并调用方法hi clas ...

  2. 工作7年收集到的git命令

    概念 git 中的术语解释: 仓库也叫版本库(repository) stage:暂存区,add 后会存到暂存区,commit 后提交到版本库 git 安装 linux 下安装 git 第一种方法:y ...

  3. css百叶窗

    效果图: css代码块: <style> *{//默认样式清除 margin: 0; padding: 0; } .content{//设置外层div的宽高,超出后隐藏 margin: 1 ...

  4. Java问题之超过数值表示范围(例如64位)结果是什么 (阶乘)

    关于老师在课上所提及的这个问题 我做了验证 截图如下 只是一个简单的计算阶乘的代码 在运行时得到了如下结果 可以看到,对于部分数字如果超出范围会从64位处自动截断,而这时由于是二进制表示,首位默认是符 ...

  5. PAT甲级英语单词整理

    proper 正确 合适 vertex(vertices)顶点 respectively 个别 分别 indices 指标 索引 shipping 运输 incompatible 不相容 oxidiz ...

  6. acwing1782 Dynamic Rankings (整体二分)

    和整体二分的模板相比,多了修改操作. 1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=1e5+10,INF=1 ...

  7. jsp页面中怎么利用a标签的href进行传递参数以及需要注意的地方

    jsp页面中: <a href="${pageContext.request.contextPath }/infoController/getProductInfo?productId ...

  8. 关于 Vue 中 h() 函数的一些东西

    最近在项目上需要一个信息弹窗,来显示信息.一开始只让它弹出了文字,而且只有一条信息.而给我的需求是多条文字和图片,而后我使用了element ui中的 Notification 通知组件来显示.当然, ...

  9. Unity——射线检测(鼠标点击开关门效果)

    Unity射线检测--实现简单的开关门效果 简要:通过鼠标点击来发射一条射线,来获得射线所碰到的物体名称,再通过改变门的Rotation值来实现开关门的效果. 一.代码实现 1.1 简易的场景搭建 注 ...

  10. Linux---配置新服务器的常见操作(CentOS7)

    修改 Centos7为字符界面 Centos7取消了之前的 inittab文件的作用,改用命令实现, systemctl get-default : 获得默认启动方式 systemctl set-de ...