flask的开发模式和生产模式(WSGI)

Flask容器化部署这篇文章介绍了一种利用WSGI技术,实现生产部署的方法。
WSGI介绍

我想了解flask run,下面是chatgpt的答复:

Flask is a micro web framework for Python that allows you to build web applications easily. When you use flask run to set up a web service, you are starting a development web server that comes bundled with Flask. This server is typically used for development and debugging purposes. It is not suitable for production use because it is single-threaded, not very robust, and not designed to handle a high volume of requests.

On the other hand, when you use a WSGI (Web Server Gateway Interface) server to deploy your Flask application, you are using a production-ready server to serve your application. WSGI is a standardized interface that allows web applications written in Python, like Flask, to be deployed on various web servers. When you deploy your Flask application with a WSGI server, such as Gunicorn, uWSGI, or mod_wsgi, you get a more robust and scalable web server setup that can handle concurrent requests and is better suited for production use.

Here are some key differences and considerations:

  1. Development vs. Production: flask run is intended for development and debugging, while WSGI servers are used in production environments.

  2. Scalability: WSGI servers can handle multiple concurrent requests and are suitable for scaling your application as traffic increases. Flask’s development server is not optimized for high concurrency.

  3. Reliability: WSGI servers are more reliable and have features like process management, worker processes, and failover mechanisms, making them better suited for handling production workloads.

  4. Deployment: When deploying your Flask application in a production environment, it’s recommended to use a WSGI server in conjunction with a reverse proxy server (like Nginx or Apache) for better performance, security, and load balancing.

In summary, while flask run is convenient for quickly testing your Flask application during development, it’s not suitable for production use. When deploying your Flask application for production, you should use a WSGI server for better performance, concurrency, and reliability.

在宿主机和容器里,分别查看ip地址

在mac上查看ip地址,比较方便的命令是

ifconfig en0 | grep inet

这条命令的解释如下

  1. Executes the "ifconfig" command to retrieve network configuration information for the "en0" network interface.
  2. Pipes (|) the output of the "ifconfig" command to the "grep inet" command.
  3. The "grep" command searches through the output and extracts any lines that contain the word "inet."

输出如下图

另外,也可以使用下面的命令查看ip地址,可以发现在宿主机和容器里,显示的ip地址是相同的。

# curl ifconfig.me
1.193.44.59#

宿主机

容器

解释如下

  • The command "curl ifconfig.me" is used to make an HTTP request to the ifconfig.me website, which is a service that provides your public IP address.

  • In the output you provided, "1.193.44.59" is the public IP address that was returned by the ifconfig.me service in response to your request. This is the public IP address that your device is using to communicate with the internet. It’s the address that other devices on the internet will see when they interact with your device.

  • Please note that public IP addresses can change, especially if you are using a dynamic IP assignment from your Internet Service Provider (ISP), so the IP address you see here may not be constant and could change over time.

在容器的bash环境里,输入hostname -i,显示当前容器对外暴露的ip地址

# hostname -i
XXX:XXXX:XXXa::d 192.168.194.13

这条命令解释如下

  • The command "hostname -i" is used to display the IP addresses associated with the current host or system. In the output you provided, you have two IP addresses listed:

    1. d07:b51a:cc66:a::d: This is an IPv6 address. IPv6 is the next-generation Internet Protocol designed to replace IPv4 due to the exhaustion of available IPv4 addresses.
    2. 192.168.194.13: This is an IPv4 address. IPv4 is the older and more widely used version of the Internet Protocol.
  • The output shows that your system has both an IPv6 and an IPv4 address associated with it. These addresses can be used for communication with other devices on a network, with IPv6 being used to support the transition to a more extensive address space as IPv4 addresses become scarcer.

查看docker 容器状态

有时候需要查看宿主机上的docker服务状态,以及哪些容器在运行或情况如何

查看docker服务状态

systemctl is-active docker

systemctl status docker

systemctl status [service name]命令会持续、实时显示相关服务的状态信息,如果要退出systemctl status状态回到提示符,可以:

Press Q: You can simply press the "Q" key on your keyboard to quit the "systemctl status" display. This will return you to the command line.

Press Ctrl + C: You can also press "Ctrl" and "C" simultaneously to send an interrupt signal to the "systemctl status" command, which will exit it and return you to the command line.

查看运行的容器状态

docker ps

查看所有容器状态

docker ps -a

重新启动k8s模拟器-minikube

节后上班第一天,发现阿里云上的minikube无法启动:

发现是没有切换到普通账号

su xxx到普通用户,重新启动minikube即可

如果要切换到root用户,输入多条命令,可以使用

sudo -i

The sudo -i command in Linux is used to open a new shell session with superuser privileges, also known as the root user. Here’s what it does:

sudo: This command is used to execute another command with superuser (or root) privileges, assuming the user running the sudo command has the necessary permissions. It’s often used to perform administrative tasks without needing to log in as the root user.

-i: This option, when used with sudo, opens a new shell session as the root user. It stands for "interactive" and is typically used when you need to perform multiple commands as the root user in an interactive shell. An interactive shell allows you to work as if you were logged in directly as the root user, with access to the root user’s environment and settings.

假期第二天在B站观看马斯克的最新对谈

B站的瓦砾村夫这个频道,搜集了很多与埃隆*马斯克有关的演讲、访谈,比在油管上观看还要方便。

比如最近在all in 论坛上,他也发表了对中美关系的看法,他认为中美关系的核心就是台湾问题,他也认为冲突可能会升级,在台海问题上摊牌,这也是越来多高科技产品被禁运的原因。

他还认为digital superintelligence是最重要的话题,比核武器还要重要。

端口的行规

下面的文章,解决了多年的一个疑惑,端口号的命名,真的有规律吗?

De Facto Ports

Most applications communicate over a TCP or UDP port. Ports 0-1023 are usually privileged and require administrator or superuser access to bind a network socket to an IP with the corresponding port. But anything over 1024 is up for grabs. IANA (Internet Assigned Numbers Authority) can “reserve” ports for specific applications — but this is only a formality; users and applications are free to use whatever port they wish.

So a look at some port numbers (1024+) and how they are used as default ports today, in 2023. There are many lists out there, but this aims to capture a list of protocols actually used in production (and leaves off many one-off ports used for specific games).

Some interesting patterns observed:

Odd-numbered and easy-to-remember ports are usually used for development servers. 3000, 5000, and 9000 are common in all-in-one web frameworks. Applications that have a related privileged application port (e.g., SMTP, DNS) sometimes use a repeated string (e.g., 5353 for Multicast DNS, 3535 for SMTP, or 8080 for a web server). Other than that, it seems like the strategy is to pick a number with low entropy (e.g., Jupyter on 8888) or a completely random one unlikely to cause conflicts (e.g., 25565 for Minecraft).

Odd-numbered and easy-to-remember ports are usually used for development servers. 3000, 5000, and 9000 are common in all-in-one web frameworks. Applications that have a related privileged application port (e.g., SMTP, DNS) sometimes use a repeated string (e.g., 5353 for Multicast DNS, 3535 for SMTP, or 8080 for a web server). Other than that, it seems like the strategy is to pick a number with low entropy (e.g., Jupyter on 8888) or a completely random one unlikely to cause conflicts (e.g., 25565 for Minecraft).

1080 — SOCK Proxy
2049 — Network File System (NFS)
2181 — Apache ZooKeeper
2375 — Docker REST API (HTTP)
2376 — Docker REST API (HTTPS)
3000 — “The Development Framework Port.” Ruby on Rails uses port 3000 as the default development port for its web server. Node frameworks use this port (e.g., Express.js, Meteor, Create React App, NextJS, SvelteJS, Astro, Remix).

3306 — MySQL

3478 — STUN, TURN (NAT Traversal)

4000 — Phoenix, Jekyll

4001 — etcd

4200 — AngularJS

4567 — Sinatra

5000 — “The Other Development Framework Port.” Flask (Python) uses 5000 as the default development port. As does ASP.NET Core.

5222 — XMPP (Extensible Messaging and Presence Protocol)

5349 — STUN, TURN over TLS

5353 — Multicast DNS — Follows the same pattern as SMTP, occasionally being run on port 3535. Duplicates the privileged port (DNS uses 53).

5432 — PostgreSQL

5900 — VNC (using a remote frame buffer, RFB)

6000 — X11 (over the network). Common to take the display number and add it to 6000 (e.g., DISPLAY 6 would be served over 6006).

6379 — Redis

6660 — IRC (Internet Relay Chat)

6881 — BitTorrent

8000 — “Python Development Framework Port.” Includes Django and Python 3’s http.server.

8080 — “The HTTP web server port.” Like 5353 (Multicast DNS) and 3535 (SMTP), an unprivileged port to run an HTTP webserver.

8333 — Bitcoin

8888 — Jupyter Notebook,

8983 — Apache Solr

9000 — Used by various applications, but no central theme or extremely well-known application.

25565 — Minecraft

27017 — MongoDB

51820 — WireGuard

CIDR与子网掩码

CIDR表示法

"10.0.0.0/26" 是使用CIDR(无类别域间路由/Classless Inter-Domain Routing)表示法来表示一个IP地址范围的方式。在CIDR表示法中,IP地址范围由一个IP地址后跟一个正斜杠和一个数字组成,该数字指定了网络前缀中的位数。下面解释一下 "10.0.0.0/26" 的含义:

IP地址:"10.0.0.0" 是该范围的基本IP地址。它是地址范围的起点。

/26:"/26" 表示子网掩码或网络前缀中的位数。在这种情况下,它表示IP地址中左边的26位用于表示网络,而剩下的6位用于表示网络内的各个主机地址。

现在,让我们更详细地解释 "10.0.0.0/26":

网络地址:"10.0.0.0" 是网络地址,表示整个网络或子网。

可用IP地址:在/26子网中,有2^6 = 64个可能的IP地址。然而,通常情况下,范围中的第一个和最后一个地址被保留用于网络标识和广播,因此在网络内有62个可用的IP地址供主机使用。

可用IP地址范围:"10.0.0.1" 到 "10.0.0.62"
子网掩码:与"/26"相关联的子网掩码以标准点分十进制格式表示为 "255.255.255.192"。以二进制表示,它是 "11111111.11111111.11111111.11000000",其中前26位被设置为 "1" 以表示网络部分,后6位被设置为 "0" 以表示主机地址。

总之,"10.0.0.0/26" 定义了一个具有64个IP地址的子网范围,从 "10.0.0.1" 到 "10.0.0.62"。这通常用于为网络段内的设备或主机分配IP地址,同时保留了网络和广播地址。

子网掩码、网络地址范围和CIDR

子网掩码、网络地址范围和CIDR(Classless Inter-Domain Routing)之间有密切的关系,它们都用于定义和描述计算机网络中的子网和网络分割。

  1. 子网掩码(Subnet Mask)

    • 子网掩码是一个32位的二进制数,用于划分IP地址中的网络部分和主机部分。它由连续的1位(网络位)和连续的0位(主机位)组成。
    • 子网掩码定义了一个IP地址的哪部分用于网络地址,哪部分用于主机地址。
    • 例如,子网掩码 255.255.255.0 表示前24位用于网络地址,后8位用于主机地址。
  2. 网络地址范围

    • 网络地址范围指的是特定子网的IP地址范围,其中包括网络地址和广播地址以及可分配的主机地址。
    • 网络地址是子网中的第一个IP地址,通常是所有主机位都为0。广播地址是子网中的最后一个IP地址,通常是所有主机位都为1。
    • 例如,对于子网掩码 255.255.255.0,网络地址范围可以是 192.168.1.0192.168.1.255。同样的,网络地址范围也可以是’172.1.1.0′ ‘172.1.1.255’
  3. CIDR(Classless Inter-Domain Routing)

    • CIDR是一种表示IP地址和子网掩码的标准方法,以便更精确地描述网络的子网划分。
    • CIDR表示法包括IP地址,后跟斜杠和网络前缀长度。网络前缀长度指定了网络位的数量,而不是使用具体的子网掩码。
    • 例如,CIDR表示法 192.168.1.0/24 表示网络前缀长度为24位,即前24位用于网络地址,后8位用于主机地址(32-24=8,2^8=256)。

关系:

  • 子网掩码用于明确指定IP地址的哪些位是网络位和哪些位是主机位。
  • 网络地址范围定义了一个子网的IP地址范围,包括网络地址、广播地址和可分配的主机地址。
  • CIDR表示法则是一种更灵活和精确的方法,使用网络前缀长度来表示网络位的数量,而不是具体的子网掩码。CIDR表示法提供了更多的灵活性,可以用于描述各种不同大小的子网,而无需使用不同的子网掩码。

举一个例子(在子网掩码为255.255.240.0时,基础网络地址为172.19.224.0)

当使用CIDR(Classless Inter-Domain Routing)表示法时,IP地址和子网掩码结合在一起,以一种更精确和紧凑的方式来表示网络的子网划分。让我详细解释为什么子网掩码 255.255.240.0 可以用CIDR表示法表示为 172.19.224.0/20

  1. 子网掩码 255.255.240.0 的二进制表示

    • 子网掩码 255.255.240.0 在二进制中是 11111111.11111111.11110000.00000000
    • 这表示前20位用于网络地址,后12位用于主机地址。
  2. IP地址 172.19.224.0 的二进制表示

    • IP地址 172.19.224.0 在二进制中是 10101100.00010011.11100000.00000000
    • 这是网络地址部分,这时候如果考虑上面的子网掩码的规定,则只有12位作为主机地址,也就是从0000.00000000开始的地址,也就是在c网段只有224~240可以作为主机网段,因为241是11110001,已经无法作为网段了。
  3. CIDR表示法的网络前缀长度

    • 为了使用CIDR表示法,我们需要确定网络位的数量,即前面有多少位用于网络地址。
    • 在这个例子中,有前20位用于网络地址。
  4. CIDR表示法的格式

    • CIDR表示法包括IP地址,后跟斜杠和网络前缀长度,例如 IP地址/网络前缀长度
  5. CIDR表示法的组合

    • 将上述的网络地址 172.19.224.0 与网络前缀长度 20 组合在一起,即 172.19.224.0/20

综上所述,CIDR表示法 172.19.224.0/20 表示网络地址 172.19.224.0 和子网掩码 255.255.240.0 结合在一起,指定了网络地址的前20位是网络位,后12位是主机位。这使得CIDR表示法成为一种更灵活、紧凑和精确的方式,用于描述网络的子网划分,而无需使用特定的子网掩码。

如何确定master nodes究竟在哪几台服务器上

k8s配合容器化技术,高度抽象了底层硬件,因此有时候我们想了解master node的具体位置,还有点困难。

第一步,先找到master nodes的名字

[root@172-20-26-79 ~]# kubectl get nodes | grep master
ks-control-1         Ready    control-plane,master   5d23h   v1.21.11
ks-control-2         Ready    control-plane,master   5d23h   v1.21.11
ks-control-3         Ready    control-plane,master   5d23h   v1.21.11

第二步,使用describe来获取内部ip的地址,从而判断是否在一台主机上(综合server的组网情况)

[root@172-20-26-79 ~]# kubectl describe nodes ks-control-3 | grep InternalIP
  InternalIP:  172.20.26.28
[root@172-20-26-79 ~]# kubectl describe nodes ks-control-2 | grep InternalIP
  InternalIP:  172.20.26.89
[root@172-20-26-79 ~]# kubectl describe nodes ks-control-1 | grep InternalIP
  InternalIP:  172.20.26.86

吾日三洗吾身

曾子说:吾日三省吾身,为人谋而不忠乎?与朋友交而不信乎?传而不习乎?

从今天,我也准备养成:三洗吾身的习惯

一洗:早晨完成100个俯卧撑后
二洗:午饭后最困倦时,大概2点左右
三洗:下班到家后

三洗都采用海军陆战队洗澡法,时常控制在端到端10分钟内,冷水。

  • 从手脚开始入浴
  • 避免浑身有汗时入浴
  • 浴后立即擦干

解决跳板机问题

公司的IDC,需要通过堡垒机登录,有两种方式

  1. 使用web shell,这个非常简单,在公司的opencloud页面上就可以使用,而且省去了输入ssh用户名和密码。
  2. 使用ssh终端,总是失败,请教了运维同事,他也不清楚,还好有chatgpt的神助攻,画了1小时解决了。

失败信息

on my mac :# ssh username@jump.server.com
Unable to negotiate with X.X.X.X port 22: no matching host key type found. Their offer: ssh-rsa

chat gpt给出的建议

It appears that you’re trying to SSH from your Mac to the server at jump.server.com, and you’re encountering the "no matching host key type found" error with an offer of "ssh-rsa." This error typically occurs when the SSH client and server cannot agree on a suitable host key algorithm.

To resolve this issue, you can use the -o option to specify the host key algorithm explicitly in your SSH command. For example, you can use the -o option to force the use of the "ssh-rsa" host key algorithm like this:

ssh -o HostKeyAlgorithms=+ssh-rsa username@jump.server.com

This command tells the SSH client to use the "ssh-rsa" host key algorithm when connecting to the server.

However, it’s worth noting that "ssh-rsa" is considered less secure than modern alternatives like "ssh-ed25519" or "ecdsa-sha2-nistp256." If possible, you should encourage the server administrator to update the SSH server’s host key algorithm configuration to use a more secure option.

Additionally, ensure that your SSH client is up to date, as older versions may not support some of the newer host key algorithms.