引言

最近做边缘计算项目,因为没有基础,所以首先学习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. Elasticsearch:Snapshot 生命周期管理

    转载自:https://blog.csdn.net/UbuntuTouch/article/details/108643226

  2. SQL通用语法和SQL分类

    SQL通用语法 1.SQL 语句可以单行或多行书写,以分号结尾 2.可使用空格和缩进来增强语句的可读性 3.MySQL 数据库的SQL语句不区分大小写,关键字建议使用大写 4.3种注释 单行注释: - ...

  3. 洛谷P4513 小白逛公园 (线段树)

    这道题看起来像是线段树和最大子段和的结合,但这里求最大子段和不用dp,充分利用线段树递归的优势来处理.个人理解:线段树相当于把求整个区间的最大子段和的问题不断划分为很多个小问题,容易解决小问题,然后递 ...

  4. python基础作业1

    目录 附加练习题(提示:一步步拆解) 1.想办法打印出jason 2.想办法打印出大宝贝 3.想办法打印出run 4.获取用户输入并打印成下列格式 5 根据用户输入内容打印其权限 6 编写用户登录程序 ...

  5. Linux中CentOS 7的安装及Linux常用命令

    1. 前言 什么是Linux Linux是一套免费使用和自由传播的操作系统.说到操作系统,大家比较熟知的应该就是Windows和MacOS操作系统,我们今天所学习的Linux也是一款操作系统. 为什么 ...

  6. 动词时态=>2.动作的时间状态结合

    动作和时间结合 现在的四种时态 现在进行时态 对于 现在这个时间点,这个 动作 还在进行当中 例如:我现在正在喝水 现在完成时态 对于 现在这个时间点,这个 动作 已然完成 例子:我现在已经喝完了水 ...

  7. python实现鼠标手动截图(类似于QQ截图)

    由于在网上找了很久,只找到按像素位置截图和全屏截图的,所以决定自己写一个. 本程序实现原理是现用PIL里的ImageGrab进行全屏截图,然后通过模拟鼠标操作,进行截图,最后删除全屏截图,只留下鼠标截 ...

  8. LINQ使用小贴士

    LINQ中的排序操作符 OrderBy:按升序对序列的元素进行排序.OrderByDescending:按降序对序列的元素排序.ThenBy:按升序对序列中的元素执行后续排序.ThenByDescen ...

  9. visual studio插件开发-Menu

    工欲善其事,必先利其器,作为程序员我们很大部分时间在和ide打交道,好的插件可以大大提高我们的编程效率,我开发过几个vs插件来解决一键生成dbmodels,快速部署到服务器,总结下来最关键的还是对于M ...

  10. nginx 客户端返回499的错误码

    我们服务器客户端一直有返回错误码499的日志,以前觉得比例不高,就没有仔细查过,最近有领导问这个问题,为什么耗时只有0.0几秒,为啥还499了?最近几天就把这个问题跟踪定位了一下,这里做个记录 网络架 ...