UseForwardedHeaders

未开启

//httpContext.GetRemoteIPAddress()
192.168.8.16
//httpContext.Connection.RemoteIpAddress
127.0.0.1
Accept = */*
Connection = close
Host = 192.168.8.121:5005
User-Agent = curl/7.81.0
X-Real-IP = 192.168.8.16
X-Forwarded-For = 192.168.8.16
X-Forwarded-Proto = http

开启,满配

builder.Services.Configure<ForwardedHeadersOptions>(options =>
{
    options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
    options.KnownProxies.Add(IPAddress.Parse("192.168.8.121"));
});
app.UseForwardedHeaders();
//httpContext.GetRemoteIPAddress()
192.168.8.16
//httpContext.Connection.RemoteIpAddress
192.168.8.16
Accept = */*
Connection = close
Host = 192.168.8.121:5005
User-Agent = curl/7.81.0
X-Real-IP = 192.168.8.16
X-Original-Proto = http
X-Original-For = [::1]:55209

开启,未配置KnownProxies

192.168.8.16
192.168.8.16
Accept = */*
Connection = close
Host = 192.168.8.121:5005
User-Agent = curl/7.81.0
X-Real-IP = 192.168.8.16
X-Original-Proto = http
X-Original-For = 127.0.0.1:55303

开启,未配置XForwardedFor

192.168.8.16
127.0.0.1
Accept = */*
Connection = close
Host = 192.168.8.121:5005
User-Agent = curl/7.81.0
X-Real-IP = 192.168.8.16
X-Forwarded-For = 192.168.8.16
X-Original-Proto = http

Console.WriteLine("Directory.GetCurrentDirectory()       " + Path.Combine(Directory.GetCurrentDirectory(), "wwwroot").ToString());
Console.WriteLine("Environment.CurrentDirectory          " + Path.Combine(Environment.CurrentDirectory, "wwwroot").ToString());
Console.WriteLine("AppDomain.CurrentDomain.BaseDirectory " + Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "wwwroot").ToString());
Console.WriteLine("AppContext.BaseDirectory              " + Path.Combine(AppContext.BaseDirectory, "wwwroot").ToString());

输出

Directory.GetCurrentDirectory()       E:\Repo\MesBased_2D\src\Entry\wwwroot
Environment.CurrentDirectory          E:\Repo\MesBased_2D\src\Entry\wwwroot
AppDomain.CurrentDomain.BaseDirectory E:\Repo\MesBased_2D\src\Entry\bin\Debug\net6.0\wwwroot
AppContext.BaseDirectory              E:\Repo\MesBased_2D\src\Entry\bin\Debug\net6.0\wwwroot

SignalR在Nginx反向代理前后端分离项目中,需要单独匹配路由。

配置如下

http {
    sendfile on;
 
    upstream app_servers {
        # 不写http,在转发处写
        server x.x.x.x:5050;
    }
 
    server {
        listen 80;
 
        location /app {
            proxy_pass         http://app_servers;
            proxy_http_version 1.1;
            proxy_set_header   Host $host;
            proxy_set_header   X-Real-IP $remote_addr;
            proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header   X-Forwarded-Host $server_name;
            proxy_set_header   Upgrade $http_upgrade;
            proxy_set_header   Connection keep-alive;
            proxy_cache_bypass $http_upgrade;
        }
        # SignalR路由
        location /app/notifications {
            proxy_pass         http://app_servers/notifications;
            proxy_http_version 1.1;
            proxy_set_header   Host $host;
            proxy_set_header   X-Real-IP $remote_addr;
            proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header   X-Forwarded-Host $server_name;
            proxy_set_header   Upgrade $http_upgrade;
            proxy_set_header   Connection "upgrade";
            proxy_cache_bypass $http_upgrade;
        }
    }
}

需求注意点:

  • upstream中定义host,如时写了http协议,那么在proxy_pass中就不要再写http,两处写一处,否则重定义报错
  • Nginx路由规则默认是大小写敏感的

    =表示精确匹配
    ^~表示url以某个常规字符串开头,理解为匹配url路径即可,nginx不对url做编码,因此请求为/static/20%/aa,可以被规则 ^$ /static/ /aa 匹配到
    ~区分大小写的正则匹配
    ~*不区分大小写的正则匹配
    !~ !~*区分大小写不匹配及不区分大小写不匹配的正则
    /通用匹配,任何请求都会匹配到

Ref

nginx 配置路由不区分大小写-腾讯云开发者社区-腾讯云 (tencent.com)

nginx详解之语法规则 - 七in秦 - 博客园 (cnblogs.com)


k8s container runtime

RuntimePath to Unix domain socket
containerdunix:///var/run/containerd/containerd.sock
CRI-Ounix:///var/run/crio/crio.sock
Docker Engine (using cri-dockerd)unix:///var/run/cri-dockerd.sock

k8s官方推荐contained,与docker解耦。用contained的话,docker无法管理k8s的镜像,必须用ctr管理。contained区分命名空间,k8s默认为k8s.io。

k8s架构

安装:containerd为容器运行时

linux环境准备

  • 设置hostname及hosts
  • 关闭swap

    # 暂时关闭
    swapoff -a
    # 永久关闭,修改/etc/fstab取消swap分区
    sudo vi /etc/fstab
    #/swap.img      none    swap    sw      0       0
  • 关闭firewall

    systemctl stop firewalld
    systemctl disable firewalld
  • 关闭selinux

    # 暂时关闭 
    setenforce 0
    # 永久关闭 
    sed -i --follow-symlinks 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/sysconfig/selinux

添加源

#添加aliyun密钥
curl -fsSL https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-archive-keyring.gpg
#添加aliyun k8s源
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-archive-keyring.gpg] https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list

安装

sudo atp-get install kubelet kubeadm kubectl docker-ce [containerd.io]

docker最好装docker-ce,docker.io没有包含containerd,还要单儿装containerd.io

以上操作在master和node节点都要执行

初始化k8s集群

在master新建集群

# 初始化集群控制台 Control plane
# 失败了必须用 kubeadm reset 重置再重试
sudo kubeadm init \
--apiserver-advertise-address=192.168.8.41 \    #主机ip
--image-repository registry.aliyuncs.com/google_containers \
--pod-network-cidr=10.244.0.0/16                #集群网络域,采用flannel用这个默认地址

# 记得把 kubeadm join xxx 保存起来
# 忘记了重新获取:kubeadm token create --print-join-command

# 复制授权文件,以便 kubectl 可以有权限访问集群
# 如果你其他节点需要访问集群,需要从主节点复制这个文件过去其他节点
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config

# 在其他机器上创建 ~/.kube/config 文件也能通过 kubectl 访问到集群

成功输出结果

Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

Alternatively, if you are the root user, you can run:

  export KUBECONFIG=/etc/kubernetes/admin.conf

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 192.168.8.41:6443 --token u0ion1.nxz86lyryfeikq1l \
        --discovery-token-ca-cert-hash sha256:8de62f9c5d16506bf6d52b1545d5ccd282e7b1e60eb2c403ec53215dc0cfeddf

子节点加入集群

sudo kubeadm join 192.168.8.41:6443 --token u0ion1.nxz86lyryfeikq1l \
        --discovery-token-ca-cert-hash sha256:8de62f9c5d16506bf6d52b1545d5ccd282e7b1e60eb2c403ec53215dc0cfeddf

配置集群网络

采用flannel插件,可选还有Calico等

在主结点执行

kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml

Troubleshoot

  • ApiService 6443 没起来

    Additionally, a control plane component may have crashed or exited when started by the container runtime.
    To troubleshoot, list all containers using your preferred container runtimes CLI.
    Here is one example how you may list all running Kubernetes containers by using crictl:
      - 'crictl --runtime-endpoint unix:///var/run/cri-dockerd.sock ps -a | grep kube | grep -v pause'
          Once you have found the failing container, you can inspect its logs with:
      - 'crictl --runtime-endpoint unix:///var/run/cri-dockerd.sock logs CONTAINERID'
    

    报错是 dial unix /var/run/cri-dockerd.sock: connect: permission denied
    解决:修改cri-dockerd.sock权限,或者把当前$USER加入docker用户组

  • Kubeadm初始化报错:[ERROR CRI]: container runtime is not running
    删阶除 rm -rf /etc/containerd/config.toml
    重启 systemctl restart containerd
  • Flannel 组网错误 "Failed to create sandbox for pod" err="rpc error: code = DeadlineExceeded desc = failed to get sandbox image \"registry.k8s.io/pause:3.8\"

    需要在ctr 里下载镜像重新tag命名,且必须在k8s.io命名空间下

  • kubeadm init 超时 ==》 没有安装containerd

Ref

注意:网上大部分教程是以docker为运行时

K8S的安装(Ubuntu 20.04) - 简书 (jianshu.com)

💽 安装 Kubernetes 集群 - K8S 教程 - 易文档 (easydoc.net)

Kubernetes 升级至 1.24 并将 container runtime 切换至 containerd - dudu - 博客园 (cnblogs.com)

mingcheng/deploy-k8s-within-aliyun-mirror: 使用阿里云镜像快速部署 Kubernetes 集群 (github.com)

guangzhengli/k8s-tutorials: k8s tutorials | k8s 教程 (github.com)


两种模式说明

  1. 直接在客户端端输入账密登录,常用在自家的一套业务系统内,客户端、资源端、认证中心都是自家的。流程为:客户端->资源端->认证中心->资源端->客户端。
  2. 客户端点击跳转到第三方页面登录,认证完成再跳回已方页面,如Github/QQ/微信/等。流程为:客户端->第三方认证中心->客户端->资源端->客户端。

    两都主要区别是请求code和Token的执行者不同,第一种都在后端(资源端),第二种请求code在前端,请求Token在后端。我开始动手时弄混了这两者,导致我来来回回改了好几次。还有其它模式,如客户端,我还没接触到。

Github OAuth 实操要点

  1. 在Github->Settings->Developers->OAuth新建OAuth工程。

    1. 主要注意redirect_uri,是请求code后返回前端的页面(前端拿到code再请求后端,后端在请求Token认证,再返回结果给后端。为啥不直接返回后端?因为直接返回后端怎么跳不回前端)。这在请求code时必填的,请求Token选填。请求时填入值必是Github上配置路径或其子路径。
    2. 开发时,可以在Github上配成127.0.0.1,或都配成发布域名,同时修改开发机的hosts把127.0.0.1指向域名。
  2. 由于网络原因,需要把请求超时设长一点,即axioas timeout。

其它看教程


第三方登录之 GitHub OAuth 的接入与使用

授权 OAuth 应用 - GitHub 文档