regular expression

java

分组捕获

1
2
3
4
5
6
7
8
9
String line = "This order was placed for QT3000! OK?";
Pattern pattern = Pattern.compile("(.*?)(\\d+)(.*)");
Matcher matcher = pattern.matcher(line);

while (matcher.find()) {
System.out.println("group 1: " + matcher.group(1));
System.out.println("group 2: " + matcher.group(2));
System.out.println("group 3: " + matcher.group(3));
}

开头结尾1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
String str="hello world,hello java,hello java";

System.out.println("===========匹配字符串===========");
//匹配str中所有字符串hello,这时str中3个hello都能匹配上,通过下面打印的匹配上的字符串的位置可以看出
Pattern p=Pattern.compile("hello");
Matcher m=p.matcher(str);
while(m.find()){
System.out.println(m.group()+" 位置:["+m.start()+","+m.end()+"]");
}
System.out.println("===========匹配字符串,并且该字符串是在开头的位置===========");
// ^表示匹配字符串的开头,但是如何在[]里面则表示非,如[^a-f] 不匹配a-f
// "hello"和"^hello"的区别就是:前者匹配时不管是不是在开头位置,只要能匹配就行,后者则是不但要能匹配而且还要是在开头的位置。这时str中3个hello只有第1个能匹配上。
p=Pattern.compile("^hello");
m=p.matcher(str);
System.out.println("is:" + m.matches());
while(m.find()){
System.out.println(m.group()+" 位置xxx:["+m.start()+","+m.end()+"]");
}

System.out.println("===========匹配字符串===========");
//这时str中两个java都能匹配上
p=Pattern.compile("java");
m=p.matcher(str);
while(m.find()){
System.out.println(m.group()+" 位置:["+m.start()+","+m.end()+"]");
}
System.out.println("===========匹配字符串,并且是该字符串是在末尾的位置===========");
//这时str中两个java只有第2个才能匹配上
p=Pattern.compile("java$");
m=p.matcher(str);
while(m.find()){
System.out.println(m.group()+" 位置:["+m.start()+","+m.end()+"]");
}

开头结尾2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 这是整个匹配,直接是String的方法
String test = "http://yahoo.com";
System.out.println(test.matches("^(http|https|ftp)://.*$"));

// 这个是编译过的表达式,也是整个匹配
Pattern p2 = Pattern.compile("^(http|https|ftp)://.*$");
Matcher m2 = p2.matcher(test);
System.out.println("m2:" + m2.matches());

// 这个是捕获group,取第一个group, index从1开始
Pattern p2 = Pattern.compile("^(http|https|ftp)://.*$");
Matcher m2 = p2.matcher(test);
if (m2.find()) {
System.out.println("g1:" + m2.group(1));
}

// 这个是group(0),没有小括号分组,从前到后匹配到什么算什么
String str="hello world,hello java,hello java";
p=Pattern.compile("java");
m=p.matcher(str);
while(m.find()){
System.out.println(m.group()+" 位置:["+m.start()+","+m.end()+"]");
}

mongodb centos7 setup

Install

Start mongodb server and autostart mongodb on boot

  • systemctl start mongod.service
  • systemctl enable mongod.service

enable remote access

update /etc/mongod.conf to bindIp: 0.0.0.0

k8s service port

总的来说,port和nodePort都是service的端口,前者暴露给集群内客户访问服务,后者暴露给集群外客户访问服务。从这两个端口到来的数据都需要经过反向代理kube-proxy流入后端pod的targetPort,从而到达pod上的容器内。

nodeport只有 type为NodePort类型的的service用

容易混淆的概念:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
1、NodePort和port

前者是将服务暴露给外部用户使用并在node上、后者则是为内部组件相互通信提供服务的,他们是在service上的端口。

2、targetPort
targetPort是pod上的端口,用来将pod内的container与外部进行通信的端口

3、port、NodePort、ContainerPort和targetPort在哪儿?

port在service上,负责处理对内的通信,clusterIP:port

NodePort在node上,负责对外通信,NodeIP:NodePort

ContainerPort在容器上,用于被pod绑定

targetPort在pod上、负责与kube-proxy代理的port和Nodeport数据进行通信

总结:targetPort很好理解,targetPort是pod上的端口,从port和nodePort上到来的数据最终经过kube-proxy流入到后端pod的targetPort上进入容器。
https://blog.csdn.net/yjk13703623757/article/details/79819415

1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: v1
kind: Service
metadata:
name: test-service
spec:
ports:
- port: 8080
targetPort: 8170
nodePort: 33333
protocol: TCP
selector:
component: test-service-app

The port is 8080 which represents that test-service can be accessed by other services in the cluster at port 8080.
The targetPort is 8170 which represents the test-service is actually running on port 8170 on pods
The nodePort is 33333 which represents that test-service can be accessed via kube-proxy on port 33333.
pod运行在targetPort为8170不代表就可以通过这个端口访问,还是得通过port的8080来访问他(cluster内部),或者nodePort的33333来访问(外部)

个人总结

nodeport是外部机器访问的端口,这个是刚刚到kube-proxy的时候,还没有进入具体的pod
targetport是具体的port的监听端口,比如mysql的3306,就是dockerfile里面的expose端口
port是内部pod直接的访问端口,这个端口也是刚刚到kube-proxy的时候,还没有进入具体的pod,这个跟nodeport一个级别,
他也是service上面的端口
比如mysql的targetport虽然是3306,但是cluster里面的pod可能通过33306来访问mysql pod

Kubernetes 分配给 Service 一个固定 IP,这是一个虚拟 IP (也称为 ClusterIP),并不是一个真实存在的IP,而是由 Kubernetes 虚拟出来的。虚拟 IP 的范围通过 Kubernetes API Service 的启动参数–service-cluster-ip-range=10.254.0.0/16 配置
虚拟 IP 属于 Kubernetes 内部的虚拟网络,外部是寻址不到的,在 Kubernetes 系统中,实际上是由 Kubernetes Proxy 组件负责实现虚拟 IP 路由和转发的,所以在 Kubernetes Node 中我们都运行了 Kubernetes Proxy,从而在容器覆盖网络之上又实现了 Kubernetes 层级的虚拟转发网络。

更新与2020/5/12
target port是 pod上面的端口, port是service的端口, nodeport是主机的端口, nodeport映射到port最终进入pod的端口targetport

https://blog.csdn.net/xinghun_4/article/details/50492041
https://hk.saowen.com/a/e185eef3635890d22291e800f123eb2b1339d5e835017ab670c88832078ea291
https://ieevee.com/tech/2017/01/20/k8s-service.html
https://stackoverflow.com/questions/49981601/difference-between-targetport-and-port-in-kubernetes-service-definition
https://wiki.shileizcc.com/confluence/pages/viewpage.action?pageId=2523170
https://juejin.im/post/5bd6c14be51d455b7461cb46

k8s deploy sample apps

Create a backend and frontend app

1
https://kubernetes.io/docs/tasks/access-application-cluster/connecting-frontend-backend/

please do not forget to change the type to NODEPORT for frontend application.
the deployment and service can be included in a single file or in separated file

Create a python app which can print the local ip

1
https://itnext.io/install-kubernetes-on-bare-metal-centos7-fba40e9bb3de

kubernetes cluster setup

kubernetes architecture

准备机器

  • 可以通过vmware创建1台centos虚拟机,我用的是7.6版本,可以从官网下载centos
  • 接下来所有的操作都是基于root用户,且需要配置科学上网,否则会遇到安装失败, 因为中间可能会访问到google地址

配置网卡

  • 安装完成之后执行nmcli d会发现网卡是禁用的,ipconfig命令执行不了
  • 关于网络配置可以参考CentOS 7 minimal 版本安装后网络配置
    • 简单来说就是在nmtui打开的gui界面里面配置网卡自动启动
  • 需要提醒的是nmtui打开的界面里面,通过tab切换按钮,通过空格而不是回车选择checkbox
  • 网卡启动之后yum install -y net-tools安装网络工d具
  • ipconfig得到ip地址之后,强烈建议使用MobaXterm连接vm, 这个比putty好用很多,免费版就够用

禁用防火墙

本地开发或者学习环境,为了简单,直接disable防火墙

1
2
systemctl disable firewalld
systemctl stop firewalld

安装 kubeadm, kubelet, kubectl, docker

  • 参考docker install来安装最新版的docker,或者直接执行下面三个命令

    1
    2
    3
    4
    5
    6
    7
    8
    9
    yum install -y yum-utils \
    device-mapper-persistent-data \
    lvm2

    yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo

    yum install docker-ce
  • 设置kubernetes repository

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    cat <<EOF > /etc/yum.repos.d/kubernetes.repo
    [kubernetes]
    name=Kubernetes
    baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
    enabled=1
    gpgcheck=1
    repo_gpgcheck=1
    gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
    exclude=kube*
    EOF
  • 安装k8s相关工具

    1
    yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes
  • Set SELinux in permissive mode (effectively disabling it)

    1
    2
    setenforce 0
    sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
  • 开机自启动kubernetes, docker

    1
    2
    3
    4
    systemctl enable kubelet
    systemctl enable docker
    systemctl restart kubelet
    systemctl restart docker
  • 关闭swap

    1
    2
    3
    4
    swapoff -a
    vi /etc/fstab
    注释掉下面这一行永久关闭swap
    #/dev/mapper/centos-swap swap swap defaults 0 0

准备其余的机器

clone这个vm生成两个新的work node,分别设置三台机器各自的主机名

1
2
3
hostnamectl set-hostname 'k8smaster'
hostnamectl set-hostname 'node1'
hostnamectl set-hostname 'node2'

Initializing your master

  • Set /proc/sys/net/bridge/bridge-nf-call-iptables to 1

    1
    2
    in master and all work nodes, execute:
    sysctl net.bridge.bridge-nf-call-iptables=1
  • 在master机器执行kubeadm init

    1
    kubeadm init --pod-network-cidr=10.244.0.0/16
  • master上面更新/root/.bash_profile
    增加下面一行,source /root/.bash_profile 立即生效

    1
    export KUBECONFIG=/etc/kubernetes/admin.conf
  • 在master上 Installing a pod network add-on

    1
    kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/bc79dd1505b0c8681ece4de4c0d86c5cd2643275/Documentation/kube-flannel.yml

Once a pod network has been installed, you can confirm that it is working by checking that the CoreDNS pod is Running in the output of
kubectl get pods –all-namespaces

  • work node上面更新/root/.bash_profile
    增加下面一行,source /root/.bash_profile 立即生效

    1
    export KUBECONFIG=/etc/kubernetes/kubelet.conf
  • 加node到cluster
    刚刚kubeadm init执行后输出的join命令可以在另外两台work node上面跑,跑完之后 Run kubectl get nodes on the master to see this machine join.

  • 总结

    1. 至此,执行kubectl get pods –all-namespaces可能会报错,可能是网络的问题, 通过journalctl -xeu kubelet查看相关日志,我是通过重启服务器来解决的
    2. 建议重启的时候先启动work node,最后启动master,然后等待5分钟执行kubectl get pods

master上配置dashboard

  • 安装dashboard
    1
    kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yaml

安装完成之后,如果发现dashboard的pod不是running状态的话,可以删除他重新执行上面的安装命令

1
kubectl --namespace kube-system delete deployment kubernetes-dashboard

不过因为没有安全证书,所以chrome和ie禁止访问,只能通过Firefox增加exception来访问,后续可以研究下更好的访问dashboard方法

设置固定ip

https://blog.csdn.net/u014466635/article/details/80284792

相关命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
kubectl exec -it  curl-66959f6557-8m7tt  -- /bin/bash
kubeadm reset
kubectl describe pods {podname}
kubectl get svc -n default
journalctl -u kubelet.service
journalctl -xeu kubelet(查看日志)
kubectl get pods --all-namespaces
kubectl get pods -n kube-system -owide
kubectl logs -n kube-system kubernetes-dashboard-56bcddb89b-wbcqg
kubectl describe pod -n istio-system istio-cleanup-secrets-vmbxl


kubectl get nodes
kubectl describe node $nodename