轻量方案:使用 Multipass(官方轻量虚拟 Ubuntu)
如果你只是想运行命令行版 Ubuntu(不需要桌面),可以用 Canonical 官方工具 Multipass。
安装:
brew install --cask multipass
创建 Ubuntu 虚拟机:
multipass launch --name ubuntu --mem 4G --disk 20G
进入虚拟机:
multipass shell ubuntu
如果你只是想运行命令行版 Ubuntu(不需要桌面),可以用 Canonical 官方工具 Multipass。
创建 Ubuntu 虚拟机:
multipass launch --name ubuntu --mem 4G --disk 20G
进入虚拟机:
multipass shell ubuntu
if don't wanna use the ip address
docker get IP address command:
docker inspect -f '{{range. NetworkSettings. Networks}}{{. IPAddress}}{{end}}' container_name_or_id
use host.docker.internal
1. appsettings.json
namespace ReactAPIApp.Server.Models{public class Driver{public int Id { get; set; }public string Name { get; set; } = null!;public int DriverNumber { get; set; }}}
4. Add Context for example add Data folder
Data/ApiDbContext.cs
using Microsoft.EntityFrameworkCore;
using ReactAPIApp.Server.Models;
dbcontext command lines:
Add-Migration initial
remove-database
update-database
scopeSearch
collect(explode(' ', $terms))->filter()->each(function ($tiem)use ($query) {
$term = '%' . $term . '%';
$query->where(function($query) use ($term) {
$query->where('first_name', 'like', $term)
->orWhere('last_name', 'like', $term)
->orWhereHas('company', function($query) use ($term) {
$query->where('name', like', $term);
});
});
});
to SQL it is
SELECT * FROM 'users'
WHERE 'first_name' LIKE '%bill%'
OR 'last_name' LIKE '%bill%'
OR EXISTS (
SELECT * FROM 'companies'
WHERE 'users'.'company_id' = 'companies'.'id'
)
model/Comment.php
public function isAuthor() {// n + 1 issue
return $this-->feature->comments->first()->user_id === $this->user_id;
}
Improves
in controllor
$feature->load('comments.user', 'comments.feature.comments');
Improves more
$feature->load('comments.user');
$feature->comments->each->setRelation('feature', $feature);
354、Kubernetes 核心实战 服务网络 Service服务发现ClusterIP方式
- servic:port的服务发现与负载均衡
集群内使用service的ip:port 就可以负载均衡的访问,
服务器内访问- 服务名.所在namespace.svc, 比如my-dep.default.svc
--port 要暴露的port
--type=ClusterIP 集群ip ,集群内部可以访问
kubectl expose deploy my-dep --port=8000 --target-port=80 (--type=ClusterIP)
--type=NodePort 集群外部也可以访问, NodePort 范围在30000 - 32767之间
kubectl expose deploy my-dep --port=8000 --target-port=80 (--type=NodePort)
查看先运行的service
kubectl get svc
删除service
kubectl delete svc my-dep
需要自己安装Ingress
测试环境
环境准备
1. 所有节点,所有机器安装
yum install -y nfs-utils
2. 主节点
1. 得到kube 的名称空间namespace, 名称空间是用来隔离资源的
kubectl get namespace
or
kubectl get ns
2. 得到pods (应用程序)的列表
kubectl get pods -A
不带-A是得到默认的应用
3. 得到指定名称空间下的应用
kubectl get pod -n 名称空间名
打印一个更完善的信息 -owide
kubectl get pod -owide
4. 创建和删除名称空间, 删除名称空间会删除名称空间下所有的应用
kubectl create ns 名称空间名
kubectl delete ns 名称空间名
删除命名空间还可以从yaml删,比如删除用配置文件hello.yaml 创建的命名空间
kubectl delete -f hello.yaml
5. 用yaml创建名称空间, 比如 hello.yaml
apiVersiion: v1
kind: Naqmespace
metadata:
name: hello
以下两行是固定的写法
apiVersiion: v1
kind: Naqmespace
最后执行命令
kubectl apply -f hello.yaml
6. 创建pot with 容器
kubectl run mynginx --image=nginx
查看pot运行情况
kubectl describe pod mynginx
查看pot运行在哪个node下,需要运行以下命令,需要在所有的node下运行一遍
docker ps|grep mynginx
删除pot
kubectl detete pod Podname
通过yaml文件创建pot with container, pod.yaml
apiVersion: v1
kind: Pod
matadata:
label:
run: mynginx
name: mynginx
namespace: default // 可有可无,如果在dashboard里操作,如果没有选择pod就需要这个
spec:
containers:
- image: nginx // 镜像名
name: mynginx // 容器名
kubectl apply -f pod.yaml
删除配置文件生成的pod
kubectl delete -f pod.yaml
查看log运行日记
kubectl logs pod名字
kubectl logs mynginx
每个pod -- k8是都会分配一个ip
比如用 kubectl get pod -owide 后会看到pod的IP地址
然后使用 curl 192.168.169.136就能看到pod的内容
集群中的任意一个机器以及任意的应用都能通过pod分配的ip来访问这个pod
进入到pod里的容器去修改
kubectl exec -it mynginx -- /bin/bash
exit // 结束修改
7. 一个pod添加多个容器
apiVersion: v1
kind: Pod
matadata:
label:
run: myapp
name: myapp
namespace: default // 可有可无,如果在dashboard里操作,如果没有选择pod就需要这个
spec:
containers:
- image: nginx // 镜像名
name: mynginx // 容器名
- image: tomcat: 8.5.68
name: tomcat
kubectl apply -f multicontainer-pod.yaml
#监视kube
watch -n l kubectl get pod
8. Deployment
kutectl create deploy mytomcat --image=tomcat:8.5.68
kutectl create deploy mytomcat --image=nginx --replicas=3 // replicas 副本, 多副本模式
删除
kubectl delete deploy mytomcat
扩容和缩容
kubectl scale deploy/mynginx --replicas=5 // 如果之前是replicas=2, 那么现在就是5个了,如果设置成 replicas=1, 那么就是缩容。
或者修改yaml
kubectl edit deploy mytomcat
滚动更新
// nginx 是current 镜像image
// nginx:1.16.1 新的要替换的镜像
// --record 记录整个过程
kubectl set image deploy/my-dep nginx=nginx:1.16.1 --record
deploy 版本回滚 rollout
1)先查看历史记录
kubectl rollout history deploy/my-dep
2) 查看某个历史详情
kubectl rollout undo deploy/my-dep -to-revision=2
3)回滚到上一次
kubectl rollout undo deploy/my-dep
4)或者回滚到指定版本
kubectl rollout undo deploy/my-dep --to-revision=2
6 部署dashboard
1) 部署
kebenetes 官方可视化界面
https://github.com/kubernetes/dashboard
1. 配置yum源
sudo yum install -y yum-utils
sudo yum-config-manager \
-- add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
2. 安装docker
sudo yum install -y docker-ce docker-ce-cli contanerd.io
3. 启动
# --now 开机启动
systemctl enable docker --now
4. 配置加速
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json << -'EOF'
{
"registry-mirrors": ["https://82m9ar63.mirror.aliyuncs.com"],
"exec-opts": ["native.cgroupdriver=systemd"],
"log-driver": "json-file",
"log-opts": {
"max-size": "100m"
},
"storage-driver": "overlay2"
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
5. 安装Kubernetes
# 设置主机名,各个机器设置自己的域名
hostnamectl set-hostname k8s-master
hostnamectl set-hostname k8s-node1
hostnamectl sethostname k8s-node2
# 将SELinux 设置为permissive 模式(相当于将其禁用) 关闭swap
sudo setenforce 0
sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
# 关闭swap
swapoff -a
sed -ri 's/.*swap.*/#&/' /etc/fstab
# 允许 iptables 检查桥接流量
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
br_netfilter
EOF
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
# 配置生效
sudo sysctl --system
6 安装三大件kubelet, kubeadm, kubectl
cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=http://..../kubernetes-el7-x86_64
enable=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=http://....../kubernetes/yum/doc/yum-key.gpg http://....../kubernetes/yum/doc/rpm-package-key.gpg
execlude=kubelet kubeadm kubectl
EOF
sudo yum install -y kubelet-1.20.9 kubeadm-1.20.9 kubectl-1.20.9 --disableexcludes=kubernetes
sudo systemctl enable --now kubelet
#检查kubelet
systemctl status kubelet
7. 使用kubeadm引导集群
# 下载各个机器需要的镜像
sudo tee ./images.sh <<-'EOF'
#! /bin/bash
images=(
kube-apiserver:v1.20.9
kube-proxy:v1.20.9
bube-controller-manager:v1.20.9
kube-scheduler:v1.20.9
coredns:1.7.0
etcd:3.4.13-0
pause:3.2
)
for imageName in ${images[@]} ; do
docker pull registry.....com/lfy_k8s_images/$imageName
done
EOF
#执行下载
chmod +x ./images.sh && ./images.sh
8. 主节点
#所有机器添加master域名映射,以下需要修改为自己的
echo "172.32.0.2 cluster-endpoint" >> /etc/hosts
# 主节点初始化
kubeadm init \
--apiserver-advertise-address=172.32.0.2 \ #这个ip一定是主节点的master ip
--control-plane-endpoint=cluster-endpoint \ #这个cluster-endpoint 是主节点域名的值
--image-repository registry.cn-hangzhou.aliyuncs.com/lfy_k8s_images \
--kubernetes-version v1.20.9 \
--service-cidr=10.96.0.0/16 \ #k8s的网络负载均衡的时候用的
--pod-network-cidr=192.168.0.0/16
#一般这个ip
不用改--service-cidr=10.96.0.0/16和--pod-network-cidr=192.168.0.0/16,如果改,ip跟所有网络范围不重叠,比如172.32.0.2
上面运行完会出现下图
这个图里有几个重要的命令行需要运行
然后运行
mkdir -p $HOME/ .kube #创建目录
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config #复制到config
sudo chown $(id -u):$(id -g) $HOME/.kube/config #给权限
如果想加入主节点需要运行,也就是别的机器当做主节点或加入到主节点,运行上图下面的命令
kubeadm join cluster-endpoint:6443 --token ......... \
--discovery-token-ca-cert-hash sha256: ...... \
--control-plane
如果想加入工作节点需要运行上图下面的操作
kubeadm join cluster-endpoint:6443 --token ......... \
--discovery-token-ca-cert-hash sha256: ......
但是加节点的生成的命令行是有时效的,24小时有效,如果超时了,需要生成新的令牌token, 所有命令都是在master里运行
kubeadm token create --print-join-command
运行kubectl get nodes 去查看nodes
在master里下载插件的配置文件,比如calico
curl https://..../calico.yaml -O
然后执行这个配置文件
kubectl apply -f calico.yaml
# 如果之前改过 --pod-network-cidr=192.168.0.0/16 的IP地址,这个时候,calico 的配置文件的ip地址也需要更改
Kubeernetes 的简单命令
# 查看集群所有节点,只能在master里查看
kubectl get nodes
# 根据配置文件,给集群创建资源
kubectl apply -f xxx.yaml
# 查看集群部署了哪些应用
docker ps
kubectal get pods -A
# 运行中的应用在docker里叫容器,在k8s里叫pod
# 节点node加入
1. Docker add and run redis:
docker run -v /data/redis/redis.conf \
-v /data/redis/data:/data \
-d -name myredius \
-p 6379:6379 \
redis:latest redis-server /etc/redis/redis.conf
2. 构建镜像
-t 标签名
-f 使用的哪个Dockerfile
. current directory
docker build -t java-demo:v1.0 .
3. docker 打包成image --- Dockerfile
#基础运行环境
FROM openjdk:8-jdk-slim
LABEL maintainer=Raymond
#需要copy 已有的java-demo-0.0.1-SNAPSHOT.jar 需要复制到current docker里
COPY target/*.jar /app.jar
#镜像的启动命令
# ENTRYPOINT or CMD
#ENTRYPOINT ["java", "-jar", "java-demo-0.0.1-SNAPSHOT.jar"]
#java-demo-0.0.1-SNAPSHOT.jar 需要复制到current docker里
#复制完之后启动的时候就用复制完的jar包 app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]
4. docker push
tag 原名
raymond docker hub 上我的文件夹
docker login
docker tag java-demo:v1.0 raymond/java-demo:v1.0
docker push raymond/java-demo:v1.0
其他环境下载后,运行
docker pull raymond/java-demo:v1.0
docker run -d -p 8080:8080 --name myjava-app raymond/java-demo:v1.0
FATAL ERROR: MarkCompactCollector: young object promotion failed Allocation failed - JavaScript heap out of memory
soulved
export NODE_OPTIONS=--max_old_space_size=4096
Another conditional operator is the "?:" (or ternary) operator.
Example #3 Assigning a default value
<?php
// Example usage for: Ternary Operator
$action = (empty($_POST['action'])) ? 'default' : $_POST['action'];
// The above is identical to this if/else statement
if (empty($_POST['action'])) {
$action = 'default';
} else {
$action = $_POST['action'];
}
?>(expr1) ? (expr2) : (expr3) evaluates to expr2 if expr1 evaluates to true, and expr3 if expr1 evaluates to false.It is possible to leave out the middle part of the ternary operator. Expression expr1 ?: expr3 returns expr1 if expr1 evaluates to true, and expr3 otherwise.
Note: Please note that the ternary operator is an expression, and that it doesn't evaluate to a variable, but to the result of an expression. This is important to know if you want to return a variable by reference. The statement
return $var == 42 ? $a : $b;in a return-by-reference function will therefore not work and a warning is issued.
Note:
It is recommended to avoid "stacking" ternary expressions. PHP's behaviour when using more than one unparenthesized ternary operator within a single expression is non-obvious compared to other languages. Indeed prior to PHP 8.0.0, ternary expressions were evaluated left-associative, instead of right-associative like most other programming languages. Relying on left-associativity is deprecated as of PHP 7.4.0. As of PHP 8.0.0, the ternary operator is non-associative.
Example #4 Non-obvious Ternary Behaviour
<?php
// on first glance, the following appears to output 'true'
echo (true ? 'true' : false ? 't' : 'f');
// however, the actual output of the above is 't' prior to PHP 8.0.0
// this is because ternary expressions are left-associative
// the following is a more obvious version of the same code as above
echo ((true ? 'true' : false) ? 't' : 'f');
// here, one can see that the first expression is evaluated to 'true', which
// in turn evaluates to (bool)true, thus returning the true branch of the
// second ternary expression.
?>
Further exists the "??" (or null coalescing) operator.
Example #5 Assigning a default value
<?php
// Example usage for: Null Coalesce Operator
$action = $_POST['action'] ?? 'default';
// The above is identical to this if/else statement
if (isset($_POST['action'])) {
$action = $_POST['action'];
} else {
$action = 'default';
}
?>(expr1) ?? (expr2) evaluates to expr2 if expr1 is null, and expr1 otherwise.In particular, this operator does not emit a notice or warning if the left-hand side value does not exist, just like isset(). This is especially useful on array keys.
Note: Please note that the null coalescing operator is an expression, and that it doesn't evaluate to a variable, but to the result of an expression. This is important to know if you want to return a variable by reference. The statement
return $foo ?? $bar;in a return-by-reference function will therefore not work and a warning is issued.
Doctrine/DBAL/Driver/PDO/Exception with message 'SQLSTATE[HY000] [2002] Connection refused'