Sunday, October 5, 2025

使用 Multipass(官方轻量虚拟 Ubuntu)

 

轻量方案:使用 Multipass(官方轻量虚拟 Ubuntu)

如果你只是想运行命令行版 Ubuntu(不需要桌面),可以用 Canonical 官方工具 Multipass。

安装:

brew install --cask multipass


创建 Ubuntu 虚拟机:

multipass launch --name ubuntu --mem 4G --disk 20G

 

进入虚拟机:

multipass shell ubuntu


删除虚拟机:
multipass delete ubuntu && multipass purge


👉 它运行的是 Ubuntu LTS,启动秒级,非常轻量。

Wednesday, November 13, 2024

docker host name/address

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

 


Monday, November 11, 2024

.Net Core connect to postgresql

 1. appsettings.json

  "ConnectionStrings": {
    "DefaultConnection": ""
  }

2. Program.cs
builder.Services.AddDbContext<ApiDbCopntext>(options => options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection")));

3. Models/ folder
add Table Class
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;

namespace ReactAPIApp.Server.Data
{
    public class ApiDbContext : DbContext
    {
        public ApiDbContext(DbContextOptions<ApiDbContext> options) : base(options){}
        public DbSet<Driver> Drivers { get; set; }
    }
}

5. run migrate command
if from package manager console
PM> Add-Migration initial

if from package manager console

Friday, November 8, 2024

js function 严格模式 use strict

 禁止function 内部的this指向winodows

class 中的function,都已默认开启了严格模式



Tuesday, October 29, 2024

.Net seed migration

dbcontext command lines:

  1. Using the Package Manager Console in Visual Studio:

Add-Migration initial 

remove-database

update-database

  1. Using the .NET Command Line Interface (.NET CLI):
dotnet ef migrations add Initial
dotnet ef database update

Saturday, July 20, 2024

Multi column searching

 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'

    )

Optimizing Circular Relationships

 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); 

Calculate totals using conditional aggregates

select 
    count(case when status = 'Requested' then 1 end) as requested,
    count(case when status = 'Planned' then 1 end) as planned,
    count(case when status = 'Completed' then 1 end) and completed,
from features

on laravel

$status = Feature::toBase() // toBase we don't want to the Feature model return back, but instead we want collection of different totals
    ->selectRaw("count(case when status = 'Requested' then 1 end) as requested")
    ->selectRaw("count(case when status = 'Planned' then 1 end) as planned")
    ->selectRaw("count(case when status = 'Completed' then 1 end) as completed")
    ->first();

we also can improve to // filter will allow you to use where statement
$status = Feature::toBase()
    ->selectRaw("count(*) filter (where status = 'Requested') as requested")
    ->selectRaw(("count(*) filter (where status = 'Planned') as planned")
    ->selectRaw(("count(*) filter (where status = 'Completed') as completed")
    ->first();

Saturday, March 18, 2023

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

测试环境





kubectl apply -f theyam.yaml

域名访问
yaml 文件

host 就是访问的域名
pathType 就是取前缀还是后缀的
path: "/" 就是域名后面的所有页面,比如 helllo.abc.com/... 






修改一个ingress
如果是修改默认的namespace就可以不用加

kubectl edit ing ingressName --namespace


https://kubernetes.github.io/ingress-nginx/examples/rewrite/


$ echo ' apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: ##要重写的地方 nginx.ingress.kubernetes.io/use-regex: "true" nginx.ingress.kubernetes.io/rewrite-target: /$2 ##要重写的地方 $2是通配符后面第二个 name: rewrite namespace: default spec: ingressClassName: nginx rules: - host: rewrite.bar.com http: paths: - path: /something(/|$)(.*) ##这里就是要重写的规则,去掉叫something的东东,把请求会转给下面的服务,
##下面的服务一定能处理这个路径,不能处理就是404error pathType: Prefix backend: service: name: http-svc port: number: 80 ' | kubectl create -f -


 环境准备

1. 所有节点,所有机器安装

yum install -y nfs-utils

2. 主节点


3.从节点


#list all of ip address
ip a

# #2: eth0: ....下面的inet 172.31.0.4就是需要替换掉上面 showmount -e 10.140.122.4 的ip address
# 也就是
showmount -e 172.31.0.4

#挂载目录
mount -t nfs 172.31.0.4:/nfs/data /nfs/data






4. 原生方式数据挂载

mkdir -p /nps/data/01
mkdir -p /nps/data/02
mkdir -p /nps/data/03





在master的root目录里创建vi pv.yaml
然后 kutectl apply -f pv.yaml

2. PVC创建与绑定

更多的

ConfigMap
配置文件挂载
vi redis.conf

#data 是所有真正的数据,key:默认是文件名 value:是配置文件的内容
完全版



查看配置集
kubectl get cm redis-conf -oyaml


创建pot
#command:
- "redis-master/redis.conf" #指的是redis容器内部的位置




检查默认配置
kubectl exec -it redis -- redis-cli

127.0.0.1:6379> CONFIG GET appendonly

配置值未更改,因为需要重新启动Pod才能从关联的ConfigMap中获取更新的值。
原因:我们的Pod部署中间件自己本身没有热更新能力









Friday, March 17, 2023

Some Kubeletes kubectl

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






Sunday, March 12, 2023

部署kubernetes 2

 6 部署dashboard

1) 部署

kebenetes 官方可视化界面

https://github.com/kubernetes/dashboard

kubectl apply -f https://raw.github....../kubernetes/dashboard/v2.3.1/aio/deploy/recomended.yaml

2)设置访问端口
kubectl edit svc kubernetes-dashboard -n kubernetes-dashboard

type: ClusterIP 改为 type: NodePort


vi dash-usr.yaml

kubectl apply -f dash-usr.yaml

获取访问令牌
kubectl -n kubernetes-dashboard get secret $(kubectl -n kubernetes-dashboard get sa/admin-user -o jsonpath="{.secrets[0].name}") -o go-template="{{.data.token | base64decode}}"

拷贝令牌
粘贴到dashboard登录的粘贴令牌的地方


Saturday, March 11, 2023

Kubernetes 部署

 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加入


Docker add Redis

  

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






Wednesday, January 12, 2022

FATAL ERROR: MarkCompactCollector: young object promotion failed Allocation failed - JavaScript heap out of memory

 FATAL ERROR: MarkCompactCollector: young object promotion failed Allocation failed - JavaScript heap out of memory

soulved

export NODE_OPTIONS=--max_old_space_size=4096

Tuesday, June 29, 2021

Ternary Operator In PHP

 

Ternary Operator ¶

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'];
}

?>
The expression (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.
?>

Null Coalescing Operator ¶

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';
}

?>
The expression (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.

?>

Wednesday, September 30, 2020

Doctrine/DBAL/Driver/PDO/Exception with message 'SQLSTATE[HY000] [2002] Connection refused'

on a new laravel project, I was trying to use php artisan migrate and get an error message: 
Doctrine/DBAL/Driver/PDO/Exception with message 'SQLSTATE[HY000] [2002] Connection refused'

and then tried to use 
php artisan tinker
DB::connection()->getPdo();
get the same error message: 

Doctrine/DBAL/Driver/PDO/Exception with message 'SQLSTATE[HY000] [2002] Connection refused'


solution:

go to .env

change the 

DB_HOST=127.0.0.1
 
to

DB_HOST=localhost

Wednesday, April 15, 2020

Starting The Scheduler

* * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1 Starting The Scheduler When using the scheduler, you only need to add the following Cron entry to your server. If you do not know how to add Cron entries to your server, consider using a service such as Laravel Forge which can manage the Cron entries for you: * * * * * cd /path-to-your-project && php artisan schedule:run >> /dev/null 2>&1 This Cron will call the Laravel command scheduler every minute. When the schedule:run command is executed, Laravel will evaluate your scheduled tasks and runs the tasks that are due. https://laravel.com/docs/6.x/scheduling#background-tasks

Wednesday, September 11, 2019