Validating Expressions

本文介绍了ASP.NET利用正则表达式验证复杂表达式的方法。通过RegularExpressionValidator控件,可指定正则表达式匹配输入文本。Visual Studio.NET能帮助创建常用正则表达式,还以美国邮编和电话号码为例,说明了该控件的使用步骤及属性设置。
Validating Expressions
What if you need to verify that text someone has entered is a correctly
formatted Canadian postal code? What if you need a user to enter a valid
e-mail address? Although you could write the necessary code to validate
these types of expressions (and many ASP developers did just that), ASP.NET
makes it easy to validate complex expressions.

Using the power of regular expressions, a widely accepted standard for
generalizing pattern matching, ASP.NET provides the
RegularExpressionValidator control. This control allows you to specify a
regular expression to match against text entered into a control. (Regular
expressions are templates for matching text梩he DOS wildcards, * and ?,
allow you to create very simple regular expression-like templates, although
real regular expressions are far more complex.)

Although coverage of creating your own regular expressions is beyond the
scope of this book (it's a huge topic, with reference books all its own),
Visual Studio .NET helps you create common regular expressions by providing
a list of the ones you're most likely to need, including U.S., French,
German, and Japanese phone numbers and postal codes, Internet e-mail
addresses, and Internet URLs.

As an example, the regular expression for U.S. ZIP codes looks like this
(remember that U.S. ZIP codes can be either five digits, such as 98765, or
five digits followed by a hyphen and four more digits, such as 98765-1234.
No other formats are allowed):

/d{5}(-/d{4})?

Here's an explanation of this example, taken apart bit by bit:

The /d{5} part of the expression matches against exactly five numeric
digits.

The (-/d{4})? part of the expression allows for the optional four digits.

The ()? part of the expression creates an optional group梕ither the whole
group appears or it doesn't. The parentheses group the expressions, and the
question mark indicates that the group is optional.

The hyphen (-) in this expression allows a hyphen as the first character in
the group.

The /d{4} part of the expression matches against four numeric digits.

To illustrate the use of this control, let's assume that on the sample
page, EmpMaint.aspx, you need to restrict data entry in the Home Phone
field to ensure valid U.S. phone numbers. You need to restrict data entry
in the Zip Code field as well. Follow these steps to add
RegularExpressionValidator controls to manage the input into these
controls, as shown in Figure 8.2:

Figure 8.2. Use the RegularExpressionValidator control to manage data input
for complex values.


Click to the right of the Zip Code text box, placing the insertion point at
that location.

In the Toolbox window, double-click the RegularExpressionValidator control,
placing a new instance on the page adjacent to the Zip Code text box.

Repeat the previous two steps for the Home Phone text box.

Set the properties for the two validation controls as shown in Table 8.5.

Table 8.5. Set These Properties for Your RegularExpressionValidator
Controls Control Property Value
RegularExpressionValidator1 ControlToValidate txtZipCode
  Display Dynamic
  ErrorMessage Enter a ZIP code in the format 99999-9999
  ValidationExpression Click the … button and select U.S. Zip Code to
insert /d{5}(-/d{4})?) 
RegularExpressionValidator2 ControlToValidate txtHomePhone
  Display Dynamic
  ErrorMessage Enter a phone number in the format (999) 999-9999
  ValidationExpression Click the … button and select U.S. Phone Number to
insert ((/(/d{3}/)?)|(/d{3}-))?/d{3}-/d{4})


After setting all the properties, view the page in Browse mode again and
verify that entering invalid ZIP code and phone number values does indeed
display error messages as the page attempts to validate the data.
nvidia@nvidia-desktop:~$ sudo systemctl status docker cri-dockerd # 确保cri-dockerd已安装(Kubernetes 1.24+必需) if ! command -v cri-dockerd &> /dev/null; then Unit cri-dockerd.service could not be found. ● docker.service - Docker Application Container Engine Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled) Active: active (running) since Mon 2025-12-08 14:21:01 CST; 10s ago TriggeredBy: ● docker.socket Docs: https://docs.docker.com Main PID: 307670 (dockerd) Tasks: 12 Memory: 32.0M CGroup: /system.slice/docker.service └─307670 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock 12月 08 14:21:00 nvidia-desktop dockerd[307670]: time="2025-12-08T14:21:00.905384514+08:00" level=info msg="Starting up" 12月 08 14:21:00 nvidia-desktop dockerd[307670]: time="2025-12-08T14:21:00.907450939+08:00" level=info msg="detected 127.0.0.53 nameserver, assuming system> 12月 08 14:21:00 nvidia-desktop dockerd[307670]: time="2025-12-08T14:21:00.933499466+08:00" level=info msg="[graphdriver] trying configured driver: overlay> 12月 08 14:21:00 nvidia-desktop dockerd[307670]: time="2025-12-08T14:21:00.950999544+08:00" level=info msg="Loading containers: start." 12月 08 14:21:01 nvidia-desktop dockerd[307670]: time="2025-12-08T14:21:01.068395372+08:00" level=info msg="Default bridge (docker0) is assigned with an IP> 12月 08 14:21:01 nvidia-desktop dockerd[307670]: time="2025-12-08T14:21:01.119938208+08:00" level=info msg="Loading containers: done." 12月 08 14:21:01 nvidia-desktop dockerd[307670]: time="2025-12-08T14:21:01.136753856+08:00" level=info msg="Docker daemon" commit="26.1.3-0ubuntu1~20.04.1"> 12月 08 14:21:01 nvidia-desktop dockerd[307670]: time="2025-12-08T14:21:01.136876237+08:00" level=info msg="Daemon has completed initialization" 12月 08 14:21:01 nvidia-desktop dockerd[307670]: time="2025-12-08T14:21:01.175939143+08:00" level=info msg="API listen on /run/docker.sock" 12月 08 14:21:01 nvidia-desktop systemd[1]: Started Docker Application Container Engine. ...skipping... Unit cri-dockerd.service could not be found. ● docker.service - Docker Application Container Engine Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled) Active: active (running) since Mon 2025-12-08 14:21:01 CST; 10s ago TriggeredBy: ● docker.socket Docs: https://docs.docker.com Main PID: 307670 (dockerd) Tasks: 12 Memory: 32.0M CGroup: /system.slice/docker.service └─307670 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock 12月 08 14:21:00 nvidia-desktop dockerd[307670]: time="2025-12-08T14:21:00.905384514+08:00" level=info msg="Starting up" 12月 08 14:21:00 nvidia-desktop dockerd[307670]: time="2025-12-08T14:21:00.907450939+08:00" level=info msg="detected 127.0.0.53 nameserver, assuming system> 12月 08 14:21:00 nvidia-desktop dockerd[307670]: time="2025-12-08T14:21:00.933499466+08:00" level=info msg="[graphdriver] trying configured driver: overlay> 12月 08 14:21:00 nvidia-desktop dockerd[307670]: time="2025-12-08T14:21:00.950999544+08:00" level=info msg="Loading containers: start." 12月 08 14:21:01 nvidia-desktop dockerd[307670]: time="2025-12-08T14:21:01.068395372+08:00" level=info msg="Default bridge (docker0) is assigned with an IP> 12月 08 14:21:01 nvidia-desktop dockerd[307670]: time="2025-12-08T14:21:01.119938208+08:00" level=info msg="Loading containers: done." 12月 08 14:21:01 nvidia-desktop dockerd[307670]: time="2025-12-08T14:21:01.136753856+08:00" level=info msg="Docker daemon" commit="26.1.3-0ubuntu1~20.04.1"> 12月 08 14:21:01 nvidia-desktop dockerd[307670]: time="2025-12-08T14:21:01.136876237+08:00" level=info msg="Daemon has completed initialization" 12月 08 14:21:01 nvidia-desktop dockerd[307670]: time="2025-12-08T14:21:01.175939143+08:00" level=info msg="API listen on /run/docker.sock" 12月 08 14:21:01 nvidia-desktop systemd[1]: Started Docker Application Container Engine. ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ...skipping... ~ Unit cri-dockerd.service could not be found. ● docker.service - Docker Application Container Engine Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled) Active: active (running) since Mon 2025-12-08 14:21:01 CST; 10s ago TriggeredBy: ● docker.socket Docs: https://docs.docker.com Main PID: 307670 (dockerd) Tasks: 12 Memory: 32.0M CGroup: /system.slice/docker.service └─307670 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock 12月 08 14:21:00 nvidia-desktop dockerd[307670]: time="2025-12-08T14:21:00.905384514+08:00" level=info msg="Starting up" 12月 08 14:21:00 nvidia-desktop dockerd[307670]: time="2025-12-08T14:21:00.907450939+08:00" level=info msg="detected 127.0.0.53 nameserver, assuming system> 12月 08 14:21:00 nvidia-desktop dockerd[307670]: time="2025-12-08T14:21:00.933499466+08:00" level=info msg="[graphdriver] trying configured driver: overlay> 12月 08 14:21:00 nvidia-desktop dockerd[307670]: time="2025-12-08T14:21:00.950999544+08:00" level=info msg="Loading containers: start." 12月 08 14:21:01 nvidia-desktop dockerd[307670]: time="2025-12-08T14:21:01.068395372+08:00" level=info msg="Default bridge (docker0) is assigned with an IP> 12月 08 14:21:01 nvidia-desktop dockerd[307670]: time="2025-12-08T14:21:01.119938208+08:00" level=info msg="Loading containers: done." 12月 08 14:21:01 nvidia-desktop dockerd[307670]: time="2025-12-08T14:21:01.136753856+08:00" level=info msg="Docker daemon" commit="26.1.3-0ubuntu1~20.04.1"> 12月 08 14:21:01 nvidia-desktop dockerd[307670]: time="2025-12-08T14:21:01.136876237+08:00" level=info msg="Daemon has completed initialization" 12月 08 14:21:01 nvidia-desktop dockerd[307670]: time="2025-12-08T14:21:01.175939143+08:00" level=info msg="API listen on /run/docker.sock" 12月 08 14:21:01 nvidia-desktop systemd[1]: Started Docker Application Container Engine. ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ...skipping... ~ Unit cri-dockerd.service could not be found. ● docker.service - Docker Application Container Engine Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled) Active: active (running) since Mon 2025-12-08 14:21:01 CST; 10s ago TriggeredBy: ● docker.socket Docs: https://docs.docker.com Main PID: 307670 (dockerd) Tasks: 12 Memory: 32.0M CGroup: /system.slice/docker.service └─307670 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock 12月 08 14:21:00 nvidia-desktop dockerd[307670]: time="2025-12-08T14:21:00.905384514+08:00" level=info msg="Starting up" 12月 08 14:21:00 nvidia-desktop dockerd[307670]: time="2025-12-08T14:21:00.907450939+08:00" level=info msg="detected 127.0.0.53 nameserver, assuming system> 12月 08 14:21:00 nvidia-desktop dockerd[307670]: time="2025-12-08T14:21:00.933499466+08:00" level=info msg="[graphdriver] trying configured driver: overlay> 12月 08 14:21:00 nvidia-desktop dockerd[307670]: time="2025-12-08T14:21:00.950999544+08:00" level=info msg="Loading containers: start." 12月 08 14:21:01 nvidia-desktop dockerd[307670]: time="2025-12-08T14:21:01.068395372+08:00" level=info msg="Default bridge (docker0) is assigned with an IP> 12月 08 14:21:01 nvidia-desktop dockerd[307670]: time="2025-12-08T14:21:01.119938208+08:00" level=info msg="Loading containers: done." 12月 08 14:21:01 nvidia-desktop dockerd[307670]: time="2025-12-08T14:21:01.136753856+08:00" level=info msg="Docker daemon" commit="26.1.3-0ubuntu1~20.04.1"> 12月 08 14:21:01 nvidia-desktop dockerd[307670]: time="2025-12-08T14:21:01.136876237+08:00" level=info msg="Daemon has completed initialization" 12月 08 14:21:01 nvidia-desktop dockerd[307670]: time="2025-12-08T14:21:01.175939143+08:00" level=info msg="API listen on /run/docker.sock" 12月 08 14:21:01 nvidia-desktop systemd[1]: Started Docker Application Container Engine. ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ! command -v cri-dockerd &> /dev/null; then wget https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.4/cri-dockerd_0.3.4.3-0.ubuntu-jammy_amd64.deb sudo dpkg -i cri-dockerd_0.3.4.3-0.ubuntu-jammy_amd64.deb fi # 重启容器运行时 sudo systemctl restart docker cri-dockerd /bin/bash: -c: line 0: syntax error near unexpected token `then' /bin/bash: -c: line 0: ` command -v cri-dockerd &> /dev/null; then' !done (press RETURN) ...skipping... ~ Unit cri-dockerd.service could not be found. ● docker.service - Docker Application Container Engine Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled) Active: active (running) since Mon 2025-12-08 14:21:01 CST; 10s ago TriggeredBy: ● docker.socket Docs: https://docs.docker.com Main PID: 307670 (dockerd) Tasks: 12 Memory: 32.0M CGroup: /system.slice/docker.service └─307670 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock 12月 08 14:21:00 nvidia-desktop dockerd[307670]: time="2025-12-08T14:21:00.905384514+08:00" level=info msg="Starting up" 12月 08 14:21:00 nvidia-desktop dockerd[307670]: time="2025-12-08T14:21:00.907450939+08:00" level=info msg="detected 127.0.0.53 nameserver, assuming system> 12月 08 14:21:00 nvidia-desktop dockerd[307670]: time="2025-12-08T14:21:00.933499466+08:00" level=info msg="[graphdriver] trying configured driver: overlay> 12月 08 14:21:00 nvidia-desktop dockerd[307670]: time="2025-12-08T14:21:00.950999544+08:00" level=info msg="Loading containers: start." 12月 08 14:21:01 nvidia-desktop dockerd[307670]: time="2025-12-08T14:21:01.068395372+08:00" level=info msg="Default bridge (docker0) is assigned with an IP> 12月 08 14:21:01 nvidia-desktop dockerd[307670]: time="2025-12-08T14:21:01.119938208+08:00" level=info msg="Loading containers: done." 12月 08 14:21:01 nvidia-desktop dockerd[307670]: time="2025-12-08T14:21:01.136753856+08:00" level=info msg="Docker daemon" commit="26.1.3-0ubuntu1~20.04.1"> 12月 08 14:21:01 nvidia-desktop dockerd[307670]: time="2025-12-08T14:21:01.136876237+08:00" level=info msg="Daemon has completed initialization" 12月 08 14:21:01 nvidia-desktop dockerd[307670]: time="2025-12-08T14:21:01.175939143+08:00" level=info msg="API listen on /run/docker.sock" 12月 08 14:21:01 nvidia-desktop systemd[1]: Started Docker Application Container Engine. ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ...skipping... SUMMARY OF LESS COMMANDS Commands marked with * may be preceded by a number, N. Notes in parentheses indicate the behavior if N is given. A key preceded by a caret indicates the Ctrl key; thus ^K is ctrl-K. h H Display this help. q :q Q :Q ZZ Exit. --------------------------------------------------------------------------- MOVING e ^E j ^N CR * Forward one line (or N lines). y ^Y k ^K ^P * Backward one line (or N lines). f ^F ^V SPACE * Forward one window (or N lines). b ^B ESC-v * Backward one window (or N lines). z * Forward one window (and set window to N). w * Backward one window (and set window to N). ESC-SPACE * Forward one window, but don't stop at end-of-file. d ^D * Forward one half-window (and set half-window to N). u ^U * Backward one half-window (and set half-window to N). ESC-) RightArrow * Right one half screen width (or N positions). ESC-( LeftArrow * Left one half screen width (or N positions). ESC-} ^RightArrow Right to last column displayed. ESC-{ ^LeftArrow Left to first column. F Forward forever; like "tail -f". ESC-F Like F but stop when search pattern is found. r ^R ^L Repaint screen. R Repaint screen, discarding buffered input. --------------------------------------------------- Default "window" is the screen height. Default "half-window" is half of the screen height. --------------------------------------------------------------------------- SEARCHING /pattern * Search forward for (N-th) matching line. ?pattern * Search backward for (N-th) matching line. n * Repeat previous search (for N-th occurrence). N * Repeat previous search in reverse direction. ESC-n * Repeat previous search, spanning files. ESC-N * Repeat previous search, reverse dir. & spanning files. ESC-u Undo (toggle) search highlighting. &pattern * Display only matching lines --------------------------------------------------- A search pattern may begin with one or more of: ^N or ! Search for NON-matching lines. ^E or * Search multiple files (pass thru END OF FILE). ^F or @ Start search at FIRST file (for /) or last file (for ?). ^K Highlight matches, but don't move (KEEP position). ^R Don't use REGULAR EXPRESSIONS. --------------------------------------------------------------------------- JUMPING g < ESC-< * Go to first line in file (or line N). G > ESC-> * Go to last line in file (or line N). p % * Go to beginning of file (or N percent into file). t * Go to the (N-th) next tag. T * Go to the (N-th) previous tag. { ( [ * Find close bracket } ) ]. } ) ] * Find open bracket { ( [. ESC-^F <c1> <c2> * Find close bracket <c2>. ESC-^B <c1> <c2> * Find open bracket <c1> --------------------------------------------------- Each "find close bracket" command goes forward to the close bracket matching the (N-th) open bracket in the top line. Each "find open bracket" command goes backward to the open bracket matching the (N-th) close bracket in the bottom line. m<letter> Mark the current top line with <letter>. M<letter> Mark the current bottom line with <letter>. '<letter> Go to a previously marked position. '' Go to the previous position. ^X^X Same as '. ESC-M<letter> Clear a mark. --------------------------------------------------- A mark is any upper-case or lower-case letter. Certain marks are predefined: ^ means beginning of the file $ means end of the file --------------------------------------------------------------------------- CHANGING FILES :e [file] Examine a new file. ^X^V Same as :e. :n * Examine the (N-th) next file from the command line. :p * Examine the (N-th) previous file from the command line. :x * Examine the first (or N-th) file from the command line. :d Delete the current file from the command line list. = ^G :f Print current file name. --------------------------------------------------------------------------- MISCELLANEOUS COMMANDS -<flag> Toggle a command line option [see OPTIONS below]. --<name> Toggle a command line option, by name. _<flag> Display the setting of a command line option. __<name> Display the setting of an option, by name. +cmd Execute the less cmd each time a new file is examined. !command Execute the shell command with $SHELL. |Xcommand Pipe file between current pos & mark X to shell command. s file Save input to a file. v Edit the current file with $VISUAL or $EDITOR. V Print version number of "less". --------------------------------------------------------------------------- OPTIONS Most options may be changed either on the command line, or from within less by using the - or -- command. Options may be given in one of two forms: either a single character preceded by a -, or a name preceded by --. -? ........ --help Display help (from command line). -a ........ --search-skip-screen Search skips current screen. -A ........ --SEARCH-SKIP-SCREEN Search starts just after target line. -b [N] .... --buffers=[N] Number of buffers. -B ........ --auto-buffers Don't automatically allocate buffers for pipes. -c ........ --clear-screen Repaint by clearing rather than scrolling. -d ........ --dumb Dumb terminal. -D [xn.n] . --color=xn.n Set screen colors. (MS-DOS only) -e -E .... --quit-at-eof --QUIT-AT-EOF Quit at end of file. -f ........ --force Force open non-regular files. -F ........ --quit-if-one-screen Quit if entire file fits on first screen. -g ........ --hilite-search Highlight only last match for searches. -G ........ --HILITE-SEARCH Don't highlight any matches for searches. -h [N] .... --max-back-scroll=[N] Backward scroll limit. -i ........ --ignore-case Ignore case in searches that do not contain uppercase. -I ........ --IGNORE-CASE Ignore case in all searches. -j [N] .... --jump-target=[N] Screen position of target lines. -J ........ --status-column Display a status column at left edge of screen. -k [file] . --lesskey-file=[file] Use a lesskey file. -K ........ --quit-on-intr Exit less in response to ctrl-C. -L ........ --no-lessopen Ignore the LESSOPEN environment variable. -m -M .... --long-prompt --LONG-PROMPT Set prompt style. -n -N .... --line-numbers --LINE-NUMBERS Don't use line numbers. -o [file] . --log-file=[file] Copy to log file (standard input only). -O [file] . --LOG-FILE=[file] Copy to log file (unconditionally overwrite). [2]+ Stopped sudo systemctl status docker cri-dockerd nvidia@nvidia-desktop:~$ # 检查Docker的cgroup驱动 nvidia@nvidia-desktop:~$ docker info | grep -i cgroup Cgroup Driver: systemd Cgroup Version: 1 nvidia@nvidia-desktop:~$ nvidia@nvidia-desktop:~$ # 如果输出是`cgroupfs`,需要改为systemd(与kubelet默认一致) nvidia@nvidia-desktop:~$ sudo tee /etc/docker/daemon.json <<EOF > { > "exec-opts": ["native.cgroupdriver=systemd"] > } > EOF { "exec-opts": ["native.cgroupdriver=systemd"] } nvidia@nvidia-desktop:~$ nvidia@nvidia-desktop:~$ # 应用配置并重启 nvidia@nvidia-desktop:~$ sudo systemctl restart docker nvidia@nvidia-desktop:~$ sudo kubeadm join 192.168.255.178:6443 \ > --token 7kaxfs.m1xlw2b4lloj20h5 \ > --discovery-token-ca-cert-hash sha256:da23339b60f174e254da99411e5799c83e2cc2e103e65dfffececca06ca8d366 \ > --cri-socket unix:///var/run/cri-dockerd.sock \ > --v=5 # 启用详细日志 I1208 14:21:46.917600 313253 join.go:412] [preflight] found NodeName empty; using OS hostname as NodeName [preflight] Running pre-flight checks I1208 14:21:46.917833 313253 preflight.go:93] [preflight] Running general checks I1208 14:21:46.921054 313253 checks.go:280] validating the existence of file /etc/kubernetes/kubelet.conf I1208 14:21:46.921089 313253 checks.go:280] validating the existence of file /etc/kubernetes/bootstrap-kubelet.conf I1208 14:21:46.921403 313253 checks.go:104] validating the container runtime I1208 14:21:46.954045 313253 checks.go:639] validating whether swap is enabled or not [WARNING Swap]: swap is enabled; production deployments should disable swap unless testing the NodeSwap feature gate of the kubelet I1208 14:21:46.954320 313253 checks.go:370] validating the presence of executable crictl I1208 14:21:46.954383 313253 checks.go:370] validating the presence of executable conntrack I1208 14:21:46.954417 313253 checks.go:370] validating the presence of executable ip I1208 14:21:46.954460 313253 checks.go:370] validating the presence of executable iptables I1208 14:21:46.954497 313253 checks.go:370] validating the presence of executable mount I1208 14:21:46.954595 313253 checks.go:370] validating the presence of executable nsenter I1208 14:21:46.954641 313253 checks.go:370] validating the presence of executable ethtool I1208 14:21:46.954669 313253 checks.go:370] validating the presence of executable tc I1208 14:21:46.954692 313253 checks.go:370] validating the presence of executable touch I1208 14:21:46.954747 313253 checks.go:516] running all checks I1208 14:21:46.965096 313253 checks.go:401] checking whether the given node name is valid and reachable using net.LookupHost I1208 14:21:46.965391 313253 checks.go:605] validating kubelet version I1208 14:21:47.033262 313253 checks.go:130] validating if the "kubelet" service is enabled and active I1208 14:21:47.049052 313253 checks.go:203] validating availability of port 10250 I1208 14:21:47.049411 313253 checks.go:280] validating the existence of file /etc/kubernetes/pki/ca.crt I1208 14:21:47.049542 313253 checks.go:430] validating if the connectivity type is via proxy or direct I1208 14:21:47.049633 313253 checks.go:329] validating the contents of file /proc/sys/net/bridge/bridge-nf-call-iptables I1208 14:21:47.049729 313253 checks.go:329] validating the contents of file /proc/sys/net/ipv4/ip_forward I1208 14:21:47.049780 313253 join.go:529] [preflight] Discovering cluster-info I1208 14:21:47.049822 313253 token.go:80] [discovery] Created cluster-info discovery client, requesting info from "192.168.255.178:6443" I1208 14:21:47.088223 313253 token.go:118] [discovery] Requesting info from "192.168.255.178:6443" again to validate TLS against the pinned public key I1208 14:21:47.124104 313253 token.go:135] [discovery] Cluster info signature and contents are valid and TLS certificate validates against pinned roots, will use API Server "192.168.255.178:6443" I1208 14:21:47.124143 313253 discovery.go:52] [discovery] Using provided TLSBootstrapToken as authentication credentials for the join process I1208 14:21:47.124173 313253 join.go:543] [preflight] Fetching init configuration I1208 14:21:47.124187 313253 join.go:589] [preflight] Retrieving KubeConfig objects [preflight] Reading configuration from the cluster... [preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -o yaml' I1208 14:21:47.151294 313253 kubelet.go:74] attempting to download the KubeletConfiguration from ConfigMap "kubelet-config" I1208 14:21:47.166584 313253 interface.go:432] Looking for default routes with IPv4 addresses I1208 14:21:47.166620 313253 interface.go:437] Default route transits interface "wlan0" I1208 14:21:47.167020 313253 interface.go:209] Interface wlan0 is up I1208 14:21:47.167131 313253 interface.go:257] Interface "wlan0" has 4 addresses :[192.168.255.72/24 2409:893d:45c:b5a1:1670:c8e4:2898:1e27/64 2409:893d:45c:b5a1:5f51:491e:9698:9815/64 fe80::417c:e3c1:2dd2:d8db/64]. I1208 14:21:47.167171 313253 interface.go:224] Checking addr 192.168.255.72/24. I1208 14:21:47.167190 313253 interface.go:231] IP found 192.168.255.72 I1208 14:21:47.167208 313253 interface.go:263] Found valid IPv4 address 192.168.255.72 for interface "wlan0". I1208 14:21:47.167218 313253 interface.go:443] Found active IP 192.168.255.72 I1208 14:21:47.172577 313253 preflight.go:104] [preflight] Running configuration dependant checks I1208 14:21:47.172634 313253 controlplaneprepare.go:225] [download-certs] Skipping certs download I1208 14:21:47.172665 313253 kubelet.go:121] [kubelet-start] writing bootstrap kubelet config file at /etc/kubernetes/bootstrap-kubelet.conf I1208 14:21:47.174216 313253 kubelet.go:136] [kubelet-start] writing CA certificate at /etc/kubernetes/pki/ca.crt I1208 14:21:47.175619 313253 kubelet.go:157] [kubelet-start] Checking for an existing Node in the cluster with name "nvidia-desktop" and status "Ready" I1208 14:21:47.186418 313253 kubelet.go:172] [kubelet-start] Stopping the kubelet [kubelet-start] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml" [kubelet-start] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env" [kubelet-start] Starting the kubelet [kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap... [kubelet-check] Initial timeout of 40s passed. [kubelet-check] It seems like the kubelet isn't running or healthy. [kubelet-check] The HTTP call equal to 'curl -sSL http://localhost:10248/healthz' failed with error: Get "http://localhost:10248/healthz": dial tcp 127.0.0.1:10248: connect: connection refused. [kubelet-check] It seems like the kubelet isn't running or healthy. [kubelet-check] The HTTP call equal to 'curl -sSL http://localhost:10248/healthz' failed with error: Get "http://localhost:10248/healthz": dial tcp 127.0.0.1:10248: connect: connection refused. [kubelet-check] It seems like the kubelet isn't running or healthy. [kubelet-check] The HTTP call equal to 'curl -sSL http://localhost:10248/healthz' failed with error: Get "http://localhost:10248/healthz": dial tcp 127.0.0.1:10248: connect: connection refused. [kubelet-check] It seems like the kubelet isn't running or healthy. [kubelet-check] The HTTP call equal to 'curl -sSL http://localhost:10248/healthz' failed with error: Get "http://localhost:10248/healthz": dial tcp 127.0.0.1:10248: connect: connection refused.
最新发布
12-09
<think>我们面对的问题是:在执行`kubeadm join`时,kubelet健康检查失败(`curl http://localhost:10248/healthz`连接被拒绝),并且`cri-dockerd`服务未找到。根据引用[1]和引用[2]的描述,可能的原因包括: 1. 未关闭交换分区(swap) 2. 节点间的Cgroup Driver不一致 3. kubelet版本与控制平面不匹配 4. 未正确安装cri-dockerd(Kubernetes 1.24+需要) ### 解决步骤 #### 1. 关闭交换分区(必须) ```bash # 临时关闭 sudo swapoff -a # 永久关闭:注释掉/etc/fstab中swap行 sudo sed -i '/swap/s/^\(.*\)$/#\1/g' /etc/fstab ``` #### 2. 确保cgroup驱动一致 ```bash # 检查Docker的cgroup驱动 docker info | grep -i cgroup # 如果输出为`cgroupfs`,而kubelet默认使用`systemd`,需要修改Docker配置 sudo tee /etc/docker/daemon.json <<EOF { "exec-opts": ["native.cgroupdriver=systemd"] } EOF sudo systemctl restart docker ``` #### 3. 安装并启动cri-dockerd(Kubernetes 1.24+必需) ```bash # 下载安装cri-dockerd wget https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.4/cri-dockerd_0.3.4.3-0.ubuntu-jammy_amd64.deb sudo dpkg -i cri-dockerd_0.3.4.3-0.ubuntu-jammy_amd64.deb # 启动并设置开机自启 sudo systemctl enable cri-dockerd.service sudo systemctl start cri-dockerd.service ``` #### 4. 清理环境并重新加入集群 ```bash # 清理之前的安装 sudo kubeadm reset --force --cri-socket unix:///var/run/cri-dockerd.sock sudo rm -rf /etc/kubernetes /var/lib/kubelet /var/lib/etcd # 重新加入集群(使用cri-dockerd) sudo kubeadm join 192.168.255.178:6443 \ --token 7kaxfs.m1xlw2b4lloj20h5 \ --discovery-token-ca-cert-hash sha256:da23339b60f174e254da99411e5799c83e2cc2e103e65dfffececca06ca8d366 \ --cri-socket unix:///var/run/cri-dockerd.sock ``` #### 5. 检查kubelet状态 ```bash # 查看kubelet日志 sudo journalctl -u kubelet -f # 如果看到错误,根据日志调整 ``` #### 6. 在主节点批准节点加入 ```bash # 在主节点执行 kubectl get nodes # 查看节点状态 kubectl get csr # 查看证书签名请求 kubectl certificate approve <csr-name> # 批准请求 ``` ### 关键点说明 - **cri-dockerd**:从Kubernetes 1.24开始,移除了对Docker的直接支持(dockershim),因此必须使用cri-dockerd作为适配器[^1]。 - **cgroup驱动**:必须确保Docker和kubelet使用相同的cgroup驱动(推荐systemd)[^1]。 - **交换分区**:Kubernetes要求关闭交换分区,否则kubelet可能无法启动[^1]。 ### 验证节点状态 在控制平面节点执行: ```bash kubectl get nodes ``` 新加入的节点状态应为`Ready`。 ### 常见问题排查 - **问题1**:`cri-dockerd`服务未安装导致`kubelet`无法与容器运行时通信。 - **问题2**:cgroup驱动不一致导致`kubelet`启动失败。 - **问题3**:交换分区未关闭导致`kubelet`拒绝启动。 通过以上步骤,应该能够解决kubelet无法启动以及加入集群失败的问题。 §§相关问题§§ 1. 如何解决Kubernetes节点状态为`NotReady`的问题? 2. Kubernetes 1.24+中如何正确配置containerd运行时? 3. 如何更新kubeadm集群的节点token? : 参考kubeadm安装集群的常见问题 [^2]: 节点kubelet服务启动失败的解决方案 [^3]: kubeadm版本管理要求 </think> ### 解决 Kubernetes 节点 kubelet 无法启动及健康检查失败问题 #### 核心问题分析 1. **cri-dockerd 服务缺失**:Kubernetes 1.24+ 移除了 dockershim,必须使用 CRI 适配器 2. **kubelet 健康检查失败**:10248 端口拒绝连接通常由运行时未就绪或配置冲突引起 3. **未关闭交换分区**:导致 kubelet 启动失败(如引用[1]所述) 4. **cgroup 驱动不一致**:Docker 与 kubelet 的 cgroup 驱动不匹配 5. **残留配置冲突**:旧集群配置未完全清除 --- ### 完整解决方案 #### 步骤 1:安装并配置 cri-dockerd(关键) ```bash # 下载并安装 cri-dockerd(适配 Kubernetes 1.24+) wget https://github.com/Mirantis/cri-dockerd/releases/download/v0.3.4/cri-dockerd_0.3.4.3-0.ubuntu-jammy_amd64.deb sudo dpkg -i cri-dockerd_0.3.4.3-0.ubuntu-jammy_amd64.deb # 配置并启动服务 sudo tee /etc/systemd/system/cri-docker.service <<'EOF' [Unit] Description=CRI Interface for Docker After=network.target docker.service [Service] ExecStart=/usr/bin/cri-dockerd --container-runtime-endpoint unix:///var/run/cri-dockerd.sock Restart=always [Install] WantedBy=multi-user.target EOF sudo systemctl daemon-reload sudo systemctl enable --now cri-docker ``` #### 步骤 2:关闭交换分区(必须) ```bash # 临时关闭 sudo swapoff -a # 永久关闭(修改 /etc/fstab) sudo sed -i '/swap/s/^\(.*\)$/#\1/g' /etc/fstab ``` #### 步骤 3:统一 cgroup 驱动 ```bash # 检查 Docker 驱动 docker info | grep -i cgroup # 若输出 cgroupfs 需修改 # 配置 Docker 使用 systemd(与 kubelet 一致) sudo tee /etc/docker/daemon.json <<EOF { "exec-opts": ["native.cgroupdriver=systemd"] } EOF sudo systemctl restart docker ``` #### 步骤 4:彻底清理环境 ```bash sudo kubeadm reset --force --cri-socket unix:///var/run/cri-dockerd.sock sudo rm -rf /etc/kubernetes /var/lib/kubelet /var/lib/etcd /etc/cni/net.d ``` #### 步骤 5:重新加入集群(使用 cri-dockerd) ```bash sudo kubeadm join 192.168.255.178:6443 \ --token 7kaxfs.m1xlw2b4lloj20h5 \ --discovery-token-ca-cert-hash sha256:da23339b60f174e254da99411e5799c83e2cc2e103e65dfffececca06ca8d366 \ --cri-socket unix:///var/run/cri-dockerd.sock ``` #### 步骤 6:诊断 kubelet 状态 ```bash # 查看实时日志 sudo journalctl -u kubelet -f --since "1 minute ago" # 验证端口监听 sudo netstat -tuln | grep 10248 # 应显示 LISTEN 状态 ``` --- ### 验证节点状态 在控制平面节点执行: ```bash kubectl get nodes ``` 新节点应显示为 `Ready` 状态 ### 故障排查表 | 现象 | 解决方案 | |------|----------| | **cri-dockerd 未运行** | `systemctl restart cri-docker` | | **10248 端口无监听** | 检查 kubelet 日志中的 CRI 连接错误 | | **cgroup 驱动不匹配** | 确认 `/etc/docker/daemon.json` 配置已应用 | | **证书错误** | 在主节点执行 `kubectl certificate approve <csr-name>` | > **关键提示**:Kubernetes 1.24+ 必须使用 cri-dockerd 或 containerd 作为运行时(如引用[3]的版本匹配要求)。节点组件版本应与控制平面匹配,偏差不超过一个次要版本。 --- ### 典型错误解决 **错误1:cri-dockerd 连接失败** ```log Failed to connect to CRI: failed to connect: context deadline exceeded ``` ➔ 确保 `cri-docker` 服务运行且套接字存在:`ls /var/run/cri-dockerd.sock` **错误2:cgroup 驱动冲突** ```log detected "cgroupfs" as Docker's cgroup driver but "systemd" in kubelet config ``` ➔ 修改 Docker 配置后必须重启:`systemctl restart docker` **错误3:证书待批准** ```log [kubelet-check] TLS bootstrap failed ``` ➔ 在主节点执行:`kubectl get csr -o name | xargs kubectl certificate approve`
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值