为了做好运维面试路上的助攻手,特整理了上百道 【运维技术栈面试题集锦】 ,让你面试不慌心不跳,高薪offer怀里抱!
这次整理的面试题,小到shell、MySQL,大到K8s等云原生技术栈,不仅适合运维新人入行面试需要,还适用于想提升进阶跳槽加薪的运维朋友。
本份面试集锦涵盖了
- 174 道运维工程师面试题
- 128道k8s面试题
- 108道shell脚本面试题
- 200道Linux面试题
- 51道docker面试题
- 35道Jenkis面试题
- 78道MongoDB面试题
- 17道ansible面试题
- 60道dubbo面试题
- 53道kafka面试
- 18道mysql面试题
- 40道nginx面试题
- 77道redis面试题
- 28道zookeeper
总计 1000+ 道面试题, 内容 又全含金量又高
- 174道运维工程师面试题
1、什么是运维?
2、在工作中,运维人员经常需要跟运营人员打交道,请问运营人员是做什么工作的?
3、现在给你三百台服务器,你怎么对他们进行管理?
4、简述raid0 raid1raid5二种工作模式的工作原理及特点
5、LVS、Nginx、HAproxy有什么区别?工作中你怎么选择?
6、Squid、Varinsh和Nginx有什么区别,工作中你怎么选择?
7、Tomcat和Resin有什么区别,工作中你怎么选择?
8、什么是中间件?什么是jdk?
9、讲述一下Tomcat8005、8009、8080三个端口的含义?
10、什么叫CDN?
11、什么叫网站灰度发布?
12、简述DNS进行域名解析的过程?
13、RabbitMQ是什么东西?
14、讲一下Keepalived的工作原理?
15、讲述一下LVS三种模式的工作过程?
16、mysql的innodb如何定位锁问题,mysql如何减少主从复制延迟?
17、如何重置mysql root密码?
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
PING www.a.shifen.com (111.13.100.92) 56(84) bytes of data.
64 bytes from promote.cache-dns.local (111.13.100.92): icmp_req=1 ttl=127 time=60.3 ms
64 bytes from promote.cache-dns.local (111.13.100.92): icmp_req=2 ttl=127 time=61.8 ms
…(以下省略)
可见ping命令可以使用了。在上面这个现象的背后,容器其实只是在镜像上面添加一个可写层,每当对这个容器进行修改都会在可写层标明与原本镜像的不同之处,当你使用`docker commit`命令时,只是提交了一个可写层,将它变成一个不可写的镜像层,而这个新的镜像和原本的镜像共享原本镜像的所有层,这就是所谓的docker分层机制,其实每个docker镜像都是由好多层构成的,这个机制能极大地缩小镜像占用的硬盘空间,如下图:
![docker分层机制](https://img-blog.csdnimg.cn/20190222195112903.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMzMjU2Njg4,size_16,color_FFFFFF,t_70)
刚刚我们运行ping命令的时候都是在前台运行的,在它运行的时候我们命令行做不了别的事情,只能眼睁睁地看它输出,使用如下命令可以让它后台运行:
docker run -d ddfddf/ping ping www.baidu.com
这个时候在控制台就看不到它的输出,使用`docker ps`可以看到这个容器的id,它是目前唯一正在运行的容器,如果想看它的输出的话可以使用`docker logs 容器ID`的方式查看。
使用`docker stop`命令可以停止这个后台运行的容器:
docker stop 2f371d67d92d
`2f371d67d92d`为这个容器在我的电脑上的ID
如果你想继续让这个容器运行,可以使用`docker start`命令:
docker start 2f371d67d92d
这个容器又会从刚才停止的地方重新运行,在初学的时候总是会搞混`docker start`与`docker run`命令,其实在理解了容器与镜像的区别之后,就很容易理解了,`docker run`使用来启动镜像的,而`docker start`是用来重新启动被停止的容器的。
只要镜像被执行了一次啊,都会生成一个新的容器,所以此时用`docker -a`会看到好多废弃的容器,可以使用`docker rm 容器ID`的方式将他们删除掉,也可以使用如下的小技巧一次性删除所有容器:
docker rm $(docker ps -a -q)
不用担心,这里只是删除所有容器而已,镜像还完好无损的保留在那里。
这里把容器和镜像容易混淆的命令总结在了下表中:
| | 删除 | 启动 |
| --- | --- | --- |
| 镜像 | docker rmi | docker run |
| 容器 | docker rm | docker start |
上文中一直使用容器ID来标明容器,其实在启动的时候可以通过–name选项来指定一个别名,之后就可以使用这个别名来代替容器ID使用,注意这个别名必须在本台机器中唯一,示例如下:
docker run -d --name=test ddfddf/ping ping www.baidu.com
docker stop test
docker rm test
上面的命令中给容器起了一个叫做test的别名,然后使用它的别名将其停止与删除。
如果有些情况下不得已要进入容器内部进行操作的话,可以使用如下命令进入容器内部的shell:
docker run -d --name=test ddfddf/tutorial ping www.baidu.com
docker exec -ti test /bin/bash
`docker exec`用于在正在运行的容器中执行命令,`-ti`选项表示分配一个虚拟终端。注意`docker exec`只能在“正在运行”的容器中执行命令,所以在`docker run`的时候执行`ping`就是为了让这个容器一直运行,而不是立即退出。
### 再聊聊仓库(Registry)
之前讲过,Docker Hub Registry是Docker的官方仓库,其实这是一个有点类似于Github的地方,任何人都可以在上面提交与下载镜像,我们可以先去上面注册一个账户(地址:<https://hub.docker.com/>),注册账户时会有谷歌的人机认证系统,所以需要一些科学上网技巧。
注册完成后可以用如下命令在shell中登录:
docker login -u 用户名 -p 密码
在将镜像push到自己新建的账户之前,要用`docker tag`重命名一下,将镜像命名`你的用户名/镜像名`这种形式,不然会push认证不通过,代码如下:
docker tag ddfddf/tutorial 你的用户名/tutorial
`docker tag`并没有干太多的事情,只是创建了一个到`ddfddf/tutorial`镜像的引用。之后就可以使用`docker push`命令将自己的镜像推送到账户中去了,方便自己和别人的使用:
docker push 你的用户名/tutorial
搞定之后就可以使用以下命令登出了:
docker logout
登录上Docker Hub,你将能看到刚刚你push上去的镜像。
### 总结
最后我再总结一下Docker的三个核心概念间的关系:
![docker核心概念及其关联](https://img-blog.csdnimg.cn/20190222195156153.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMzMjU2Njg4,size_16,color_FFFFFF,t_70)
## Dockerfile
---
如果你想要从一个基础镜像开始建立一个自定义镜像,可以选择一步一步进行构建,也可以选择写一个配置文件,然后一条命令(`docker build`)完成构建,显然配置文件的方式可以更好地应对需求的变更,这个配置文件就是Dockerfile。
学习Dockerfile的最好方式就是阅读别人写的Dockerfile,遇到不会的指令就查一查Dockerfile的文档,文档地址如下:
<https://docs.docker.com/engine/reference/builder/>
大家遇到不知道的指令多去里面翻一翻,下面我带着大家读几个开源Dockerfile,在读的过程中学习相关知识。
第一个Dockerfile以阿里中间件大赛给的`debian-jdk8`镜像为例,Dockerfile文件如下:
FROM debian:stretch
ARG DEBIAN_FRONTEND=noninteractive
ARG JAVA_VERSION=8
ARG JAVA_UPDATE=172
ARG JAVA_BUILD=11
ARG JAVA_PACKAGE=jdk
ARG JAVA_HASH=a58eab1ec242421181065cdc37240b08
ENV LANG C.UTF-8
ENV JAVA_HOME=/opt/jdk
ENV PATH=
P
A
T
H
:
{PATH}:
PATH:{JAVA_HOME}/bin
RUN set -ex
&& apt-get update
&& apt-get -y install ca-certificates wget unzip
&& wget -q --header “Cookie: oraclelicense=accept-securebackup-cookie”
-O /tmp/java.tar.gz
http://download.oracle.com/otn-pub/java/jdk/
J
A
V
A
V
E
R
S
I
O
N
u
{JAVA_VERSION}u
JAVAVERSIONu{JAVA_UPDATE}-b
J
A
V
A
B
U
I
L
D
/
{JAVA_BUILD}/
JAVABUILD/{JAVA_HASH}/
J
A
V
A
P
A
C
K
A
G
E
−
{JAVA_PACKAGE}-
JAVAPACKAGE−{JAVA_VERSION}uKaTeX parse error: Expected 'EOF', got '&' at position 35: …-x64.tar.gz \ &̲& CHECKSUM=(wget -q -O - https://www.oracle.com/webfolder/s/digest/
J
A
V
A
V
E
R
S
I
O
N
u
{JAVA_VERSION}u
JAVAVERSIONu{JAVA_UPDATE}checksum.html | grep -E “
J
A
V
A
P
A
C
K
A
G
E
−
{JAVA_PACKAGE}-
JAVAPACKAGE−{JAVA_VERSION}uKaTeX parse error: Expected 'EOF', got '&' at position 90: …f2 | xargs) \ &̲& echo "{CHECKSUM} /tmp/java.tar.gz” > /tmp/java.tar.gz.sha256
&& sha256sum -c /tmp/java.tar.gz.sha256
&& mkdir ${JAVA_HOME}
&& tar -xzf /tmp/java.tar.gz -C KaTeX parse error: Expected 'EOF', got '&' at position 37: …omponents=1 \ &̲& wget -q --hea…{JAVA_VERSION}/jce_policy-${JAVA_VERSION}.zip
&& unzip -jo -d ${JAVA_HOME}/jre/lib/security /tmp/jce_policy.zip
&& rm -rf ${JAVA_HOME}/jar/lib/security/README.txt
/var/lib/apt/lists/*
/tmp/*
/root/.wget-hsts
在解释含义之前,我们先体验一下如何用Dockerfile打包一个镜像,新建一个空目录,假设就是`~/debian-jdk8`吧,cd进这个目录,新建一个`Dockerfile`,然后把上面的内容copy进去,然后执行下面的命令:
docker build -t debian-jdk8:v1.0 .
其中`-t debian-jdk8:v1.0`表示打包的镜像名为debian-jdk,tag为v1.0(前面说过,tag是可以任意命名的,不一定要是这种格式),注意命令的最后有一个`.`,这个表示打包的上下文(其实就是Dockerfile所在目录)是在当前目录,然后目录下的Dockerfile就会被编译执行。
执行完毕后运行`docker images`就会发现多了一个`debian-jdk8`镜像。
下面来解释一下Dockerfile的结构,那些字母全部大写的每行第一个单词都是Dockerfile的指令,可以看出这个Dockefile中包括的指令有`FROM`、`ARG`、`ENV`、`RUN`,下面的表格中我对其含义进行了解释:
| 指令 | 含义解释 |
| --- | --- |
| FROM | `FROM debian:stretch`表示以`debian:stretch`作为基础镜像进行构建 |
| RUN | 可以看出`RUN`后面跟的其实就是一些shell命令,通过&&将这些脚本连接在了一行执行,这么做的原因是为了减少镜像的层数,每多一行`RUN`都会给镜像增加一层,所以这里选择将所有命令联结在一起执行以减少层数 |
| ARG | 特地将这个指令放在RUN之后讲解,这个指令可以进行一些宏定义,比如我定义`ENV JAVA_HOME=/opt/jdk`,之后RUN后面的shell命令中的`${JAVA_HOME}`都会被`/opt/jdk`代替 |
| ENV | 可以看出这个指令的作用是在shell中设置一些环境变量(其实就是export) |
### 多阶段构建(multi-stage build)
这个功能是在Docker17.05版本及以上才出现的,主要用于解决docker镜像构建的中间冗余文件的处理,这里只做简要介绍,更详细的解释请看官方文档:
<https://docs.docker.com/develop/develop-images/multistage-build/>
有的时候会看见一些古怪,里面会有多个`FROM`指令或者`FROM...AS...`指令(这都是多阶段构建的标志),比如如下的dockerfile(来源于阿里中间件大赛的agent-demp,完整项目请见:<https://github.com/DQinYuan/Agent-demo>):
Builder container
FROM registry.cn-hangzhou.aliyuncs.com/aliware2018/services AS builder
COPY . /root/workspace/agent
WORKDIR /root/workspace/agent
RUN set -ex && mvn clean package
Runner container
FROM registry.cn-hangzhou.aliyuncs.com/aliware2018/debian-jdk8
COPY --from=builder /root/workspace/services/mesh-provider/target/mesh-provider-1.0-SNAPSHOT.jar /root/dists/mesh-provider.jar
COPY --from=builder /root/workspace/services/mesh-consumer/target/mesh-consumer-1.0-SNAPSHOT.jar /root/dists/mesh-consumer.jar
COPY --from=builder /root/workspace/agent/mesh-agent/target/mesh-agent-1.0-SNAPSHOT.jar /root/dists/mesh-agent.jar
COPY --from=builder /usr/local/bin/docker-entrypoint.sh /usr/local/bin
COPY start-agent.sh /usr/local/bin
RUN set -ex && mkdir -p /root/logs
ENTRYPOINT [“docker-entrypoint.sh”]
如果你懒得点进去我刚刚给出的完整项目地址,看下面的截图也大概知道是什么样子了:
![agent-demo项目结构](https://img-blog.csdnimg.cn/20190222195248955.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMzMjU2Njg4,size_16,color_FFFFFF,t_70)
可以看出这是一个Java的Maven项目。
先解释几个之前没解释过的指令:
| 指令 | 含义解释 |
| --- | --- |
| FROM…AS… | 这是Docker 17.05及以上版本新出来的指令,其实就是给这个阶段的镜像起个别名:`FROM ...(基础镜像) AS ...(别名)`,在后面引用这个阶段的镜像时直接使用别名就可以了 |
| COPY | 顾名思义,就是用来来回复制文件的,`COPY . /root/workspace/agent`表示将当前文件夹(`.`表示当前文件夹,即Dockerfile所在文件夹)的所以文件拷贝到容器的`/root/workspace/agent`文件夹中。通过`--from`参数也可以从前面阶段的镜像中拷贝文件过来,比如`--from=builder`表示文件来源不是本地文件系统,而是之前的别名为builder的容器 |
| WORKDIR | 在执行`RUN`后面的shell命令前会先`cd`进`WORKDIR`后面的目录 |
| ENTRYPOINT | 这个参数表示镜像的“入口”,镜像打包完成之后,使用`docker run`命令运行这个镜像时,其实就是执行这个ENTRYPOINT后面的可执行文件(一般是一个shell脚本文件),也可以通过`["可执行文件", "参数1", "参数2"]`这种方式来赋予可执行文件的执行参数,这个“入口”执行的工作目录也是`WORKDIR`后面的那个目录 |
知道上面这些指令后尝试阅读一下之前给出的Dockerfile。按照官方文档的说法,多阶段构建中每一个`FROM`指令表示开始一个阶段,第一阶段从第一个`FROM`开始,在第二个`FROM`之前结束,片段如下:
Builder container
FROM registry.cn-hangzhou.aliyuncs.com/aliware2018/services AS builder
COPY . /root/workspace/agent
WORKDIR /root/workspace/agent
RUN set -ex && mvn clean package
可以看出第一阶段做的事情其实就是把项目拷贝到镜像(`COPY . /root/workspace/agent`)中用maven打包(`mvn clean package`)一下。
第二阶段的片段如下:
Runner container
FROM registry.cn-hangzhou.aliyuncs.com/aliware2018/debian-jdk8
COPY --from=builder /root/workspace/services/mesh-provider/target/mesh-provider-1.0-SNAPSHOT.jar /root/dists/mesh-provider.jar
COPY --from=builder /root/workspace/services/mesh-consumer/target/mesh-consumer-1.0-SNAPSHOT.jar /root/dists/mesh-consumer.jar
COPY --from=builder /root/workspace/agent/mesh-agent/target/mesh-agent-1.0-SNAPSHOT.jar /root/dists/mesh-agent.jar
COPY --from=builder /usr/local/bin/docker-entrypoint.sh /usr/local/bin
COPY start-agent.sh /usr/local/bin
RUN set -ex && mkdir -p /root/logs
ENTRYPOINT [“docker-entrypoint.sh”]
这个阶段的核心就是大量的`COPY`指令,从上一阶段别名为`builder`的镜像中拷贝一些执行文件过来。
这两个阶段构建结束后,第一阶段生成的镜像会被抛弃,只有最后一个阶段构建的镜像会被构建成为最终的镜像。
因为在第二阶段中只是拷贝了一些必要的执行文件过去,第一阶段在maven打包过程中产生的大量冗余文件就被抛弃了,所以说善于使用多阶段构建可以大大减小镜像的大小。
更多的关于Dockerfile的最佳实践请参考官网的一篇文章:
<https://docs.docker.com/develop/develop-images/dockerfile_best-practices/>
## END
---
感谢阅读
![](https://img-blog.csdnimg.cn/img_convert/9a8cb5f8c0ec69e6499adead0da6e95b.png)
最全的Linux教程,Linux从入门到精通
======================
1. **linux从入门到精通(第2版)**
2. **Linux系统移植**
3. **Linux驱动开发入门与实战**
4. **LINUX 系统移植 第2版**
5. **Linux开源网络全栈详解 从DPDK到OpenFlow**
![华为18级工程师呕心沥血撰写3000页Linux学习笔记教程](https://img-blog.csdnimg.cn/img_convert/59742364bb1338737fe2d315a9e2ec54.png)
第一份《Linux从入门到精通》466页
====================
内容简介
====
本书是获得了很多读者好评的Linux经典畅销书**《Linux从入门到精通》的第2版**。本书第1版出版后曾经多次印刷,并被51CTO读书频道评为“最受读者喜爱的原创IT技术图书奖”。本书第﹖版以最新的Ubuntu 12.04为版本,循序渐进地向读者介绍了Linux 的基础应用、系统管理、网络应用、娱乐和办公、程序开发、服务器配置、系统安全等。本书附带1张光盘,内容为本书配套多媒体教学视频。另外,本书还为读者提供了大量的Linux学习资料和Ubuntu安装镜像文件,供读者免费下载。
![华为18级工程师呕心沥血撰写3000页Linux学习笔记教程](https://img-blog.csdnimg.cn/img_convert/9d4aefb6a92edea27b825e59aa1f2c54.png)
**本书适合广大Linux初中级用户、开源软件爱好者和大专院校的学生阅读,同时也非常适合准备从事Linux平台开发的各类人员。**
> 需要《Linux入门到精通》、《linux系统移植》、《Linux驱动开发入门实战》、《Linux开源网络全栈》电子书籍及教程的工程师朋友们劳烦您转发+评论
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化的资料的朋友,可以点击这里获取!](https://bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
mg_convert/9d4aefb6a92edea27b825e59aa1f2c54.png)
**本书适合广大Linux初中级用户、开源软件爱好者和大专院校的学生阅读,同时也非常适合准备从事Linux平台开发的各类人员。**
> 需要《Linux入门到精通》、《linux系统移植》、《Linux驱动开发入门实战》、《Linux开源网络全栈》电子书籍及教程的工程师朋友们劳烦您转发+评论
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**[需要这份系统化的资料的朋友,可以点击这里获取!](https://bbs.csdn.net/forums/4f45ff00ff254613a03fab5e56a57acb)**
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**