centos 特权模式,centos7如何切换到图形界面
Centos 虚拟化之 XEN
我还是一个视觉系的,很多东西都感觉知道,但不能好好的去表达,还是看图好一点。
上菜。。。
OK,这是一张关于xen的架构图(来自于马哥),从这张图上,我们可以看出xen是一个type-II的虚拟化实现,type-II是在硬件之上直接安装一个Hypervisor,再在Hypervisor上安装各Guest,可上面的图好像有点不同啊。
不错,在计算机的世界里,实际就是在实现现实世界中的各种事物,如简单的1+1,又如实现一个国家的信息管控,但计算机的世界和现实世界是完全不一样的,那么要在计算机的世界里实现现实世界的事物就不可能1:1的实现。人生活现实中,而计算机的世界却是人去构建的,如何完美。
这在计算机世界中处处可见.......
上面这么多的废话,就是xen为什么不是一个我们定义的type-II的标准样子。下面我们来说说原因,xen如何要做到一个标准的type-II,那么它就要能够和所有的硬件打交道,换句话说,就是要驱动所有的硬件,而硬件的驱动一般都是由硬件生产商开发的,
(这里开启吐槽模式,intel没有提供8代cpu的部分驱动对win7的支持,导致好长一段时间我们都不能愉快的玩耍,wan e de intel!)
linux对硬件的支持都不能说很好,linux不能说多普及,但在很多领域中也是广泛使用的,但有的硬件就是不支持。
那xen呢,它没法到找所有的硬件制造商让他们开发吧,那怎么办,自己开发吗?这是不可能完成的。
办法总比问题多,好吧,没有驱动,我就用别人的好了,于是就出现上面的那种结构,xen的hypervisor只负责对硬件cpu和内存的驱动,而其它硬件如:I/O设备等的驱动托管给了dom0(linux)。
半方大的空白 或 空白
全方大的空白 或 空白
不断行的空白 或 空白
Xen Hypervisor是直接运行在硬件与所有操作系统之间的基本软件层。它负责为运行在硬件设备上的不同种类的虚拟机(不同操作系统)进行CPU调度和内存分配。Xen Hypervisor对虚拟机来说不单单是硬件的抽象接口,同时也控制虚拟机的执行,让他们之间共享通用的处理环境。
Xen Hypervisor不负责处理诸如网络、外部存储设备、视频或其他通用的I/O处理。
Domain 0是经过修改的Linux内核,是运行在Xen Hypervisor之上独一无二的虚拟机,拥有访问物理I/O资源的特权,并且可以与其他运行在Xen Hypervisor之上的其他虚拟机进行交互。所有的Xen虚拟环境都需要先运行Domain 0,然后才能运行其他的虚拟客户机。
Domain 0在Xen中担任管理员的角色,它负责管理其他虚拟客户机。
在Domain 0中包含两个驱动程序,用于支持其他客户虚拟机对于网络和硬盘的访问请求。这两个驱动分别是Network Backend Driver和Block Backend Driver。 Network Backend Driver直接与本地的网络硬件进行通信,用于处理来自Domain U客户机的所有关于网络的虚拟机请求。根据Domain U发出的请求Block Backend Driver直接与本地的存储设备进行通信然后将数据读写到存储设备上。
Domain U客户虚拟机没有直接访问物理硬件的权限。所有在Xen Hypervisor上运行的半虚拟化客户虚拟机(简称:Domain U PV Guests)都是被修改过的基于Linux的操作系统、Solaris、FreeBSD和其他基于UNIX的操作系统。所有完全虚拟化客户虚拟机(简称:Domain U HVM Guests)则是标准的Windows和其他任何一种未被修改过的操作系统。
说了这么多,下面来说说安装,惯例,上菜...
因为这个源的针对性很强,而且其中有kernel的包,以免以后忘记出
现问题,关闭这个安装源,安装时使用"--enablerepo="来安装,另外这个repo源是Centos提供的,url为 ,慢就一个字,我只用镜像源。
呵呵...
一直一直就这个,好nb的启动界面(我无数次的以为死机了,无数次...,直到有一次启动的时候我去干其它事儿去了,回来一看,神奇的事情发生了,启动成功。我再呵呵)long long ago...过程我就不说了,不堪回首!
这样可以看到xen的启动
dom0的启动看不到
好吧这个问题跳过。。。。。(再次道歉ing...)
看来现在一切正常了可以建虚拟机了吧,go go go
第一步,神说:要有硬盘,于是就有了qemu-img
第二步,神还说:要有网卡,于是就有了我敲键盘
准备工作做完了,现在该我说了,写配置文件
找度娘,找啊找。。。说是使用vnc可以,好,改
5900开了,连上去
轻松愉快吧,可以好像还有很多的问题不是吗?
xl是什么?
sdl为什么不能用?
系统要怎么安装?
配置文件只能手写吗?
vnclisten='0.0.0.0',为什么要写这个?
记一次容器环境下出现 Address not available
pod创建后一段时间一直是正常运行,突然有一天发现没有新的连接创建了,业务上是通过 pod A访问 svc B的 svc name的方式,进入 pod手动去 wget一下,发现报错了 Address not available。为何会报错这个呢?
错误代码参考连接:[errno.3]
通过 netstat-an查看到连接 svc的地址,其中 estab状态的连接数,已经到达了可用的随机端口数量阈值,无法在新建连接了。
最后通过修改了内核参数随机端口 net.ipv4.ip_local_port_range端口范围才得以解决的。
Linux的内核定义的随机端口 32768~ 60999,可能在业务设计场景中,比较容易被忽略的,我们都知道,每一个 TCP连接都是由四元组(源 IP,源端口,目的 IP,目的端口)构成的,只要四元组中其中一个元组发生了变化,就可以创建一个 TCP连接的。当一个 POD要访问一个固定的目的 IP+目的端口的时候,那么每一个 TCP连接的变量就只剩下源端口是随机的了,所以如果在需求就是需要创建大量长连接的话,要么就调大内核随机端口,要么就调整业务。
相关内核参考连接:[ip-sysctl.txt]
手动调小了 net.ipv4.ip_local_port_range,之后进行复现。
同样的问题,分别尝试了 curl,nc,wget命令,报错都不一样,这就犯难了。
那么就通过 strace命令进程分析一下看看,跟踪指定系统调用名称它们都会创建 socket(),然后发现 wget/curl命令是通过 connect()函数,而 nc命令先是是通过 bind()函数调用,如果报错就不会继续调用 connect()函数了。
通过 B/S架构的分析如下,connect()是在客户端创建 socket后建立的。
为什么 wget/curl同样调用的是 connect()函数报错的,为何报错还是不一样的?为什么 connect()函数和 bind()函数报错不一样?是不是所有情况下都是这样输出呢?
直接找了一台 Centos7.9的系统,安装 curl、wget、 nc等工具,同样改小端口范围的情况下会出现如下报错 Cannot assign requested address,某些镜像(alpine、busybox)里,使用相同命令工具对相同的情况下报错会不同。因为这些镜像里可能为了缩小整个镜像大小,对于一些基础命令都会选择 busybox工具箱(上面的 wget和 nc就来自于 busybox工具箱里的,参考 busybox文档:Busybox Command Help)来使用,所以就造成在问题定位方面困扰了。
Linux系统中用于包含与错误码相关的定义:/usr/include/asm-generic/errno.h
容器环境下,端口配置最佳实践可修改范围理论上是 0~65535,但是 0~1023是特权端口,已经预留给一下标准服务,如 HTTP:80,SSH:22等,只能特权用户使用,同时也避免未授权的用户通过流量特征攻击等所以建议端口调大的话可以将随机端口范围限制在 1024-65535之间。
如何正确配置 Pod源端口普通 Pod源端口修改方法从 kubernetes社区得知可以通过安全上下文修改 securityContext,还有可以通过 initContainers容器给特权模式 mount-o remount rw/proc/sys的方式修改,此修改方式只会在 pod的网络命名空间中生效。
hostnetwork模式 pod修改注意事项1.22+集群以上就不建议修改 net.ipv4.ip_local_port_range,因为这会和 ServiceNodePortRange产生冲突。
Kubernetes的 ServiceNodePortRange默认是 30000~32767,Kubernetes 1.22及以后的版本,去除了 kube-proxy监听 NodePort的逻辑,如果有监听的话,应用程序在选用随机端口的时候,会避开这些监听中的端口。如果 net.ipv4.ip_local_port_range的范围和 ServiceNodePortRange存在重叠,由于去掉了监听 NodePort的逻辑,应用程序在选用随机端口的时候就可能选中重叠部分,比如 30000~32767,在当 NodePort与内核 net.ipv4.ip_local_port_range范围有冲突的情况下,可能会导致偶发的 TCP无法连接的情况,可能导致健康检查失败、业务访问异常等问题。
大量创建 svc的时候减少创建监听的步骤只是提交 ipvs/iptables规则,这样可以优化连接性能。另一个就解决某些场景下出现大量的 CLOSE_WAIT占用 TCP连接等问题。在 1.22版本之后就去掉了 PortOpener逻辑。
kubernetes/pkg/proxy/iptables/proxier.go Line 1304 in f98f27b具体是如何冲突的呢?测试环境是 k8s 1.22.10,kube-proxy网络模式 ipvs。以 kubelet健康检查为例,调整了节点的内核参数 net.ipv4.ip_local_port_range为 1 024~65535。
部署 tcpdump抓包,抓到有健康检查失败的事件后,停止抓包。看到 kubelet是用节点 IP(192.168.66.27)+随机端口 32582向 pod发起了 TCP握手 podIP(192.168.66.65)+80,但是 pod在 TCP握手时回 SYN ACK给 kubelet的时候,目标端口是 32582,却一直在重传。因为这个随机端口刚好是某一个服务的 nodeport,所以优先被 IPVS拦截给规则后端的服务,但这个后端服务(192.168.66.9)并没有发起和 podIP(192.168.66.65)TCP建连,所以后端服务(192.168.66.9)直接是丢弃的。那么 kubelet就不会收到 SYN ACK回应,TCP无法建联,所以导致健康检查失败。
增加前置判断,通过 initContainers容器修改的时候,如果 podIP和 hostIP不相等才修改 net.ipv4.ip_local_port_range参数,避免误操作导致修改节点的内核参数。
如何正确配置 NodePort范围在 Kubernetes中,APIServer提供了 ServiceNodePortRange参数(命令行参数--service-node-port-range),该参数是用于限制 NodePort或 LoadBalancer类型的 Service在节点上所监听的 NodePort端口范围,该参数默认值为 30000~32767。在 ACK Pro集群中,您可以通过自定义 Pro集群的管控面参数修改该端口范围。具体操作,请参见自定义 ACK Pro集群的管控面参数。
相关链接:[1] errno.3
man7.org/linux/man-page...
[2] ip-sysctl.txt
kernel.org/doc/Document...
[3] Busybox Command Help
busybox.net/downloads/B...
[4] securityContext
kubernetes.io/docs/task...
[5] Kubernetes社区PR
github.com/kubernetes/k...
[6] f98f27b
github.com/kubernetes/k...
[7]自定义ACK Pro集群的管控面参数
help.aliyun.com/zh/ack/...
如何在docker centos容器中使用systemd
由于以下几个原因,docker的官方centos镜像中没有提供systemd服务:
systemd依赖于CAP_SYS_ADMIN capability.意味着运行Docker容器需要获得–privileged.这不利于一个base image;
systemd依赖于访问cgroups filesystem;
systemd有很多并不重要的文件存放在一个docker容器中,如果不删除它们会产生一些错误;
注意
在大规模Docker容器或集群等环境下,并不推荐使用Systemd来管理服务,还是使用诸如 Kubernetes、compose等管理工具吧。但在可控、几个容器环境下,我们还是希望使用systemd来方便管理我们的服务,那如何开启systemd呢?别急,请看下面。
1)首先创建一个Dockerfile用来创建systemd的base image,即父镜像。如下所示:
FROM centos:latest
MAINTAINER"xuchao"<xiaoxu790@126.com>
RUN yum-y install systemd systemd-libs
RUN yum clean all;\
(cd/lib/systemd/system/sysinit.target.wants/; for i in*;\
do [$i== systemd-tmpfiles-setup.service ]|| rm-f$i; done);\
rm-f/lib/systemd/system/multi-user.target.wants/*;\
rm-f/etc/systemd/system/*.wants/*;\
rm-f/lib/systemd/system/local-fs.target.wants/*;\
rm-f/lib/systemd/system/sockets.target.wants/*udev*;\
rm-f/lib/systemd/system/sockets.target.wants/*initctl*;\
rm-f/lib/systemd/system/basic.target.wants/*;\
rm-f/lib/systemd/system/anaconda.target.wants/*;
VOLUME ["/sys/fs/cgroup" ]
CMD ["/usr/sbin/init"]
2)执行docker build命令,来创建一个有systemd的base image:
# docker build--rm-t systemd/centos7.
3)OK后,查看下我们build好的已有docker镜像。
# docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
systemd/centos7 latest 25de776022cb 59 minutes ago 314.8 MB
docker.io/centos latest a65193109361 3 weeks ago 196.7 MB
4)下面,我们就可以基于这个Systemd的镜像来创建所需要的其他服务的镜像了,比如Mariadb。当然这里就还需要另外一个Dockerfile。如下所示:
FROM systemd/centos7
MAINTAINER"xuchao"<xiaoxu790@126.com>
RUN yum-y install mariadb-server mariadb; systemctl enable mariadb.service
RUN yum clean all
EXPOSE 3306
CMD ["/usr/sbin/init"]
5)为避免冲突,执行如下步骤前,需要先将上述的Dockerfile文件重命名为其他名称。
同样的,执行docker build命令来创建一个我们需要的Mariadb镜像。
# docker build-t mariadb/centos7.
6)OK后,再查看下我们build好的已有docker镜像。
# docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
mariadb/centos7 latest 9ed032ae46c3 13 minutes ago 555.1 MB
systemd/centos7 latest 25de776022cb 59 minutes ago 314.8 MB
docker.io/centos latest a65193109361 3 weeks ago 196.7 MB
7)不出所料,镜像都已经build OK了。
下面,我们就需要启动这个Mariadb的docker镜像了(注意需要使用参数–privileged)。如下所示:
# docker run--privileged-d-v/sys/fs/cgroup:/sys/fs/cgroup:ro-h systemd_mariadb-p 3306:3306-t mariadb/centos7
8)执行后续步骤前,我们需要先获取下该镜像启动后的容器ID。如下所示:
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d6a080adf45a mariadb/centos7"/usr/sbin/init" 22 minutes ago Up 22 minutes 0.0.0.0:3306->3306/tcp determined_heisenberg
9)通过下面的命令在容器内执行命令:(其中d6a080adf45a为容器ID):
# docker exec d6a080adf45a ps-ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 14:32? 00:00:00/usr/sbin/init
root 17 1 0 14:32? 00:00:00/usr/lib/systemd/systemd-journald
mysql 18 1 0 14:32? 00:00:00/bin/sh/usr/libexec/mariadb-prepare-db-dir mariadb.service
root 38 1 0 14:32? 00:00:00 [dbus-daemon]<defunct>
mysql 39 18 0 14:33? 00:00:00/bin/sh/usr/libexec/mariadb-prepare-db-dir mariadb.service
mysql 40 39 0 14:33? 00:00:00 systemctl show-p Group mariadb.service
mysql 41 39 0 14:33? 00:00:00 sed s/^Group=//
root 42 0 0 14:33? 00:00:00 ps-ef
10)由此可见,Mariadb数据库服务已经正常启动起来了。
当然,我们还可以以交互式方式进入到该容器内,执行相关操作,比如验证systemctl命令。
# docker exec-it d6a080adf45a bash
[root@systemd_mariadb/]# systemctl status mariadb
● mariadb.service- MariaDB database server
Loaded: loaded(/usr/lib/systemd/system/mariadb.service; enabled; vendor preset: disabled)
Active: active(running) since Sat 2016-06-25 14:33:51 UTC; 1min 40s ago
Process: 101 ExecStartPost=/usr/libexec/mariadb-wait-ready$MAINPID(code=exited, status=0/SUCCESS)
Process: 18 ExecStartPre=/usr/libexec/mariadb-prepare-db-dir%n(code=exited, status=0/SUCCESS)
Main PID: 100(mysqld_safe)
CGroup:/system.slice/docker-d6a080adf45a2d4c4c5d203cbe7aa354dbef886be3da296edf70e75267e9f05f.scope/system.slice/mariadb.service
├─100/bin/sh/usr/bin/mysqld_safe--basedir=/usr
└─256/usr/libexec/mysqld--basedir=/usr--datadir=/var/lib/mysql--plugin-dir=/usr/lib64/mysql/plugin--log-error=/var...
......................
OK,整个流程就讲完了。但有个遗留的问题,即:使用systemctl restart命令重启服务