<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Заметки on Ilya Pavlov</title><link>https://devmem.ru/posts/</link><description>Recent content in Заметки on Ilya Pavlov</description><generator>Hugo -- gohugo.io</generator><language>ru</language><copyright>&lt;a href='https://creativecommons.org/licenses/by-nc/4.0/' target='_blank' rel='noopener'>CC BY-NC 4.0&lt;/a></copyright><lastBuildDate>Thu, 31 Mar 2022 16:42:00 +0300</lastBuildDate><atom:link href="https://devmem.ru/posts/index.xml" rel="self" type="application/rss+xml"/><item><title>Увеличение тома Longhorn при использовании операторов Kubernetes</title><link>https://devmem.ru/posts/2022/resize-longhorn-volume/</link><pubDate>Thu, 31 Mar 2022 16:42:00 +0300</pubDate><guid>https://devmem.ru/posts/2022/resize-longhorn-volume/</guid><description>Проблемы Longhorn не поддерживает изменение размера томов на лету, поэтому том должен быть отключен (Detached), а следовательно под, использующий том, должен быть удален. А перед этим нужно удалить StatefulSet или Deployment. Операторы Kubernetes постоянно отслеживают и исправляют состояние, например, создают удаленные вручную StatefulSet или Deployment. StatefulSet не поддерживает изменение volumeClaimTemplates. Решение для StatefulSet на примере kube-prometheus-stack (Prometheus Operator) и ArgoCD Отключить или настроить все операторы, выполняющие согласование (reconciliation) объектов Kubernetes, с которыми связан целевой том:</description><content type="html"><![CDATA[<h2 id="проблемы">Проблемы</h2>
<ul>
<li>Longhorn не поддерживает изменение размера томов на лету, поэтому том должен быть отключен (Detached), а следовательно под, использующий том, должен быть удален. А перед этим нужно удалить StatefulSet или Deployment.</li>
<li>Операторы Kubernetes постоянно отслеживают и исправляют состояние, например, создают удаленные вручную StatefulSet или Deployment.</li>
<li>StatefulSet не поддерживает изменение volumeClaimTemplates.</li>
</ul>
<h2 id="решение-для-statefulset-на-примере-kube-prometheus-stack-prometheus-operator-и-argocd">Решение для StatefulSet на примере kube-prometheus-stack (Prometheus Operator) и ArgoCD</h2>
<ol>
<li>
<p>Отключить или настроить все операторы, выполняющие согласование (reconciliation) объектов Kubernetes, с которыми связан целевой том:</p>
<ol>
<li>
<p>Отключить автоматическую синхронизацию и исправление приложения в <a href="https://argo-cd.readthedocs.io/en/stable/user-guide/auto_sync/">ArgoCD</a>: в коде удалить блок <code>Application.spec.syncPolicy</code> и отправить в репозиторий, дождаться синхронизации</p>
</li>
<li>
<p>Уменьшить реплики Prometheus Operator до 0</p>
<p><code>kubectl -n observability scale deployment kps-operator --replicas 0</code></p>
</li>
</ol>
</li>
<li>
<p>Удалить StatefulSet, но оставить зависимые объекты (Pod, PersistentVolumeClaim)</p>
<p><code>kubectl -n observability delete statefulsets.apps prometheus-kps-prometheus --cascade=orphan</code></p>
</li>
<li>
<p>Удалить Pod, тем самым переведя том Longhorn в состояние Detached</p>
<p><code>kubectl -n observability delete pod prometheus-kps-prometheus-0</code></p>
</li>
<li>
<p>Отредактировать PersistentVolumeClaim, указав новый размер в <code>spec.resources.requests.storage</code></p>
<p><code>kubectl -n observability edit pvc prometheus-kps-prometheus-db-prometheus-kps-prometheus-0</code></p>
</li>
<li>
<p>Дождаться применения изменений драйвером Longhorn</p>
<p><code>kubectl -n observability describe pvc prometheus-kps-prometheus-db-prometheus-kps-prometheus-0</code></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-console" data-lang="console"><span style="display:flex;"><span>  Events:
</span></span><span style="display:flex;"><span>    Type     Reason                  Age   From                                 Message
</span></span><span style="display:flex;"><span>    ----     ------                  ----  ----                                 -------
</span></span><span style="display:flex;"><span>    Warning  ExternalExpanding       34s   volume_expand                        Ignoring the PVC: didn&#39;t find a plugin capable of expanding the volume; waiting for an external controller to process this PVC.
</span></span><span style="display:flex;"><span>    Normal   Resizing                34s   external-resizer driver.longhorn.io  External resizer is resizing volume pvc-a4de8e0e-c664-4f60-be90-ddb0207eae7f
</span></span><span style="display:flex;"><span>    Normal   VolumeResizeSuccessful  22s   external-resizer driver.longhorn.io  Resize volume succeeded
</span></span></code></pre></div></li>
<li>
<p>Задать в коде новый размер PersistentVolumeClaim в <code>prometheusSpec.storageSpec.volumeClaimTemplate.spec.resources.requests.storage</code></p>
</li>
<li>
<p>Вернуть в коде <code>Application.spec.syncPolicy</code>, отправить в репозиторий, запустить синхронизацию в ArgoCD</p>
</li>
<li>
<p>Вернуть исходное количество реплик оператора из п.1, в результате чего оператор пересоздаст удаленный ранее StatefulSet</p>
<p><code>kubectl -n observability scale deployment kps-operator --replicas 1</code></p>
</li>
</ol>
<h2 id="решение-для-deployment">Решение для Deployment</h2>
<ol>
<li>Удалить в коде <code>Application.spec.syncPolicy</code>, отправить в репозиторий, дождаться синхронизации ArgoCD</li>
<li>Удалить Deployment</li>
<li>Задать в коде новый размер <code>PersistentVolumeClaim</code>, отправить в репозиторий, запустить синхронизацию только ресурса PersistentVolumeClaim в ArgoCD, а не всего приложения</li>
<li>Дождаться применения изменений драйвером Longhorn</li>
<li>Вернуть в коде <code>Application.spec.syncPolicy</code>, отправить в репозиторий, запустить синхронизацию в ArgoCD</li>
</ol>
<h2 id="ссылки-по-теме">Ссылки по теме</h2>
<ul>
<li><a href="https://longhorn.io/docs/1.3.0/volumes-and-nodes/expansion/">https://longhorn.io/docs/1.3.0/volumes-and-nodes/expansion/</a></li>
<li><a href="https://itnext.io/resizing-statefulset-persistent-volumes-with-zero-downtime-916ebc65b1d4">https://itnext.io/resizing-statefulset-persistent-volumes-with-zero-downtime-916ebc65b1d4</a></li>
</ul>
]]></content></item><item><title>WireGuard VPN туннель между двумя серверами на Debian</title><link>https://devmem.ru/posts/2019/wireguard-vpn-tunnel-mezhdu-dvumya-serverami-na-debian/</link><pubDate>Fri, 14 Jun 2019 08:29:35 +0000</pubDate><guid>https://devmem.ru/posts/2019/wireguard-vpn-tunnel-mezhdu-dvumya-serverami-na-debian/</guid><description>Задача Организовать доступ через интернет к серверу, который находится за NAT на неподконтрольном маршрутизаторе с динамическим серым внешним IP, соответственно проброс портов с этого маршрутизатора невозможен. Перефразируя в реальный пример: нужно открывать сайт, размещенный на сервере в здании московской школы, через интернет. Интернет в здании предоставляется по госконтракту, оборудование сети школой не контролируется.
Решить эту задачу можно с помощью проброса портов через VPN-туннель между самым дешевым VPS в интернете с публичным IP-адресом и сервером/маршрутизатором внутри локальной сети.</description><content type="html"><![CDATA[<h2 id="задача">Задача</h2>
<p>Организовать доступ через интернет к серверу, который находится за NAT на неподконтрольном маршрутизаторе с динамическим серым внешним IP, соответственно проброс портов с этого маршрутизатора невозможен. Перефразируя в реальный пример: нужно открывать сайт, размещенный на сервере в здании московской школы, через интернет. Интернет в здании предоставляется по госконтракту, оборудование сети школой не контролируется.</p>
<p>Решить эту задачу можно с помощью проброса портов через VPN-туннель между самым дешевым VPS в интернете с публичным IP-адресом и сервером/маршрутизатором внутри локальной сети. Туннель будет на основе <a href="https://www.wireguard.com/">WireGuard</a> - простого, современного и быстрого VPN-протокола с минимумом настроек без возни с сертификатами и шифрами (привет, OpenVPN).</p>
<p>В статье используются виртуальные машины на Debian 9:</p>
<ol>
<li><strong>wg-lab-01</strong>, 192.168.1.101 - сервер WireGuard «VPS в интернете»</li>
<li><strong>wg-lab-02</strong>, 192.168.1.102 - клиент WireGuard «роутер за NAT»</li>
<li><strong>wg-lab-03</strong>, 192.168.1.103 - веб-сервер</li>
</ol>
<p>Пусть ВМ wg-lab-01 имеет публичный IP-адрес и будет использоваться как сервер Wireguard (к нему будут подключаться клиенты) и маршрутизатор для проброса портов на ВМ wg-lab-02, используемую как клиент Wireguard (будет инициализировать подключение к серверу) и маршрутизатор. С ВМ wg-lab-02 те же порты будут перенаправляться на ВМ wg-lab-03, на которой запущен веб-сервер nginx, а в настройках сетевого подключения IP-адрес ВМ wg-lab-02 указан в качестве шлюза по умолчанию (Default gateway).</p>
<p>Трафик должен проходить следующим образом:</p>
<blockquote>
<p>посетитель сайта &lt;-&gt; интернет &lt;-&gt; wg-lab-01 &lt;-&gt; [туннель wireguard] &lt;-&gt; wg-lab-02 &lt;-&gt; wg-lab-03</p>
</blockquote>
<p>Для упрощения конфигурации, весь трафик wg-lab-02 идет через туннель, а также все ВМ запущены внутри одного VLAN.</p>
<h2 id="настройка-туннеля-и-маршрутизации">Настройка туннеля и маршрутизации</h2>
<p>Все настройки выполняются через SSH от имени пользователя root.</p>
<h3 id="1-на-wg-lab-01-и-wg-lab-02">1. На wg-lab-01 и wg-lab-02</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span><span style="color:#75715e"># Установить wireguard</span>
</span></span><span style="display:flex;"><span>echo <span style="color:#e6db74">&#34;deb http://deb.debian.org/debian/ unstable main&#34;</span> &gt; /etc/apt/sources.list.d/unstable-wireguard.list;
</span></span><span style="display:flex;"><span>printf <span style="color:#e6db74">&#39;Package: *\nPin: release a=unstable\nPin-Priority: 90\n&#39;</span> &gt; /etc/apt/preferences.d/limit-unstable;
</span></span><span style="display:flex;"><span>apt update <span style="color:#f92672">&amp;&amp;</span> apt list --upgradable;
</span></span><span style="display:flex;"><span>apt full-upgrade;
</span></span><span style="display:flex;"><span>apt install wireguard tcpdump iptables-save;
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Включить маршрутизацию</span>
</span></span><span style="display:flex;"><span>sed -i <span style="color:#e6db74">&#39;s/^#net.ipv4.ip_forward=1/net.ipv4.ip_forward=1/&#39;</span> /etc/sysctl.conf;
</span></span><span style="display:flex;"><span>sysctl -p;
</span></span><span style="display:flex;"><span>reboot;
</span></span><span style="display:flex;"><span><span style="color:#75715e"># Сгенерировать ключи wireguard</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">(</span>umask <span style="color:#ae81ff">077</span> <span style="color:#f92672">&amp;&amp;</span> printf <span style="color:#e6db74">&#34;[Interface]\nPrivateKey = &#34;</span> | tee /etc/wireguard/wg0.conf &gt; /dev/null<span style="color:#f92672">)</span>;
</span></span><span style="display:flex;"><span>wg genkey | tee -a /etc/wireguard/wg0.conf | wg pubkey | tee /etc/wireguard/publickey;
</span></span></code></pre></div><h3 id="2-на-wg-lab-01">2. На wg-lab-01</h3>
<p>Отредактировать файл конфигурации <code>nano /etc/wireguard/wg0.conf</code></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ini" data-lang="ini"><span style="display:flex;"><span><span style="color:#66d9ef">[Interface]</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Address</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">10.255.255.1/24</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">SaveConfig</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">true</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">PostUp</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">iptables -A FORWARD -i wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">PostDown</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">iptables -D FORWARD -i wg0 -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">ListenPort</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">51820</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">PrivateKey</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">В ФАЙЛЕ КЛЮЧ УЖЕ ДОЛЖЕН БЫТЬ</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">[Peer]</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">PublicKey</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">публичный ключ с wg-lab-02 # см. в файле /etc/wireguard/publickey</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">AllowedIPs</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">10.255.255.2/32</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">PersistentKeepalive</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">10</span>
</span></span></code></pre></div><h3 id="3-на-wg-lab-02">3. На wg-lab-02</h3>
<p>Отредактировать файл конфигурации <code>nano /etc/wireguard/wg0.conf</code></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ini" data-lang="ini"><span style="display:flex;"><span><span style="color:#66d9ef">[Interface]</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Address</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">10.255.255.2/24</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">SaveConfig</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">true</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">PostUp</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">iptables -A FORWARD -i eth0 -j ACCEPT; iptables -t nat -A POSTROUTING -o wg0 -j MASQUERADE</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">PostDown</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">iptables -D FORWARD -i eth0 -j ACCEPT; iptables -t nat -D POSTROUTING -o wg0 -j MASQUERADE</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">PrivateKey</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">В ФАЙЛЕ КЛЮЧ УЖЕ ДОЛЖЕН БЫТЬ</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#66d9ef">[Peer]</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">Endpoint</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">192.168.1.101:51820</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">PublicKey</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">публичный ключ с wg-lab-01 # см. в файле /etc/wireguard/publickey</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">AllowedIPs</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">0.0.0.0/0</span>
</span></span><span style="display:flex;"><span><span style="color:#a6e22e">PersistentKeepalive</span> <span style="color:#f92672">=</span> <span style="color:#e6db74">10</span>
</span></span></code></pre></div><h3 id="4-на-wg-lab-01-и-wg-lab-02">4. На wg-lab-01 и wg-lab-02</h3>
<p>Включить автозапуск интерфейса wg0</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>systemctl enable wg-quick@wg0;
</span></span><span style="display:flex;"><span>wg-quick up wg0
</span></span></code></pre></div><h3 id="проверить-что-туннель-и-маршрутизация-работают-на-wg-lab-02">Проверить, что туннель и маршрутизация работают (на wg-lab-02)</h3>
<ul>
<li>В выводе команды <code>wg</code> присутствует строка <em>latest handshake</em></li>
<li>Адрес интерфейса wg0 на сервере wg-lab-01 пингуется <code>ping 10.255.255.1</code></li>
<li>В выводе команды <code>traceroute ya.ru</code> первый прыжок на 10.255.255.1</li>
<li>Если бы настраивали через реальный VPS в интернете, то команда <code>host myip.opendns.com resolver1.opendns.com</code> показывала бы IP-адрес VPS, а не текущего подключения к интернету</li>
</ul>
<h2 id="настройка-веб-сервера">Настройка веб-сервера</h2>
<h3 id="на-wg-lab-03">На wg-lab-03</h3>
<ol>
<li>Установить и запустить веб-сервер nginx командой <code>apt install nginx</code>, или, если установлен Docker, командой <code>docker run –name nginx -d -p 80:80 –restart unless-stopped nginx:alpine</code></li>
<li>Проверить доступность веб-сервера по текущему IP-адресу, полученному через DHCP (см. <code>ip a</code>)</li>
<li>Настроить статический IP-адрес и указать шлюз по умолчанию IP сервера wg-lab-02, перезагрузить для применения настроек</li>
</ol>
<h2 id="проброс-портов">Проброс портов</h2>
<h3 id="на-wg-lab-01">На wg-lab-01</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>iptables -t nat -A PREROUTING -d 192.168.1.101/32 -p tcp -m multiport --dports 80,443 -j DNAT --to-destination 10.255.255.2
</span></span></code></pre></div><h3 id="на-wg-lab-02">На wg-lab-02</h3>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span>iptables -t nat -A PREROUTING -d 10.255.255.2/32 -p tcp -m multiport --dports 80,443 -j DNAT --to-destination 192.168.1.103
</span></span></code></pre></div><p>Настроенные таким образом правила iptables работают до перезагрузки. Чтобы сделать правила постоянными, нужно либо сохранить их с помощью команды <code>iptables-save &gt; /etc/iptables/rules.v4</code>, либо соответствующим образом дополнить строки PostUp и PostDown в файлах /etc/wireguard/wg0.conf на обоих ВМ с Wireguard, чтобы правила применялись при активации интерфейса wg0.</p>
<p>Проверить активные правила можно командой <code>iptables -t nat -L -n -v</code></p>
<h3 id="проверить-что-проброс-портов-работает">Проверить, что проброс портов работает</h3>
<p>В браузере открыть IP-адрес wg-lab-01 (192.168.1.101) и убедиться, что открывается страница с веб-сервера на wg-lab-03.</p>
<h2 id="ссылки">Ссылки</h2>
<ul>
<li><a href="https://angristan.xyz/how-to-setup-vpn-server-wireguard-nat-ipv6/">https://angristan.xyz/how-to-setup-vpn-server-wireguard-nat-ipv6/</a></li>
<li><a href="https://nfalcone.net/blog/wireguard-vpn-debian-server/">https://nfalcone.net/blog/wireguard-vpn-debian-server/</a></li>
<li><a href="https://wiki.debian.org/WireGuard">https://wiki.debian.org/WireGuard</a></li>
<li><a href="https://wiki.debian.org/iptables">https://wiki.debian.org/iptables</a></li>
<li><a href="http://linux-ip.net/html/nat-dnat.html">http://linux-ip.net/html/nat-dnat.html</a></li>
<li><a href="https://www.revsys.com/writings/quicktips/nat.html">https://www.revsys.com/writings/quicktips/nat.html</a></li>
<li><a href="https://wiki.yobi.be/index.php/Wireguard">https://wiki.yobi.be/index.php/Wireguard</a></li>
<li><a href="https://www.ericlight.com/wireguard-part-two-vpn-routing.html">https://www.ericlight.com/wireguard-part-two-vpn-routing.html</a></li>
<li><a href="https://www.ckn.io/blog/2017/11/14/wireguard-vpn-typical-setup/">https://www.ckn.io/blog/2017/11/14/wireguard-vpn-typical-setup/</a></li>
<li><a href="https://bneijt.nl/blog/post/wireguard-vpn-using-an-edgerouter-x/">https://bneijt.nl/blog/post/wireguard-vpn-using-an-edgerouter-x/</a></li>
<li><a href="https://andrew.dunn.dev/posts/wireguard-from-your-isp/">https://andrew.dunn.dev/posts/wireguard-from-your-isp/</a></li>
</ul>
]]></content></item><item><title>Как в Экселе…</title><link>https://devmem.ru/posts/2017/kak-v-eksele/</link><pubDate>Thu, 08 Jun 2017 13:46:43 +0000</pubDate><guid>https://devmem.ru/posts/2017/kak-v-eksele/</guid><description>Когда нужно оформить список работников отдела для поощрения или отчёт о работе менеджеров, многие используют Microsoft Excel. А если задача чуть сложнее простого перечисления фамилий в столбик, то постоянно возникает вопрос «Как в экселе сделать что-то».
За время работы у меня собралось несколько полезных формул для обработки ячеек с ФИО и мобильными телефонами, которые постоянно находят своё применение.
Как в Экселе …сократить ФИО до инициалов (Фамилия И.О.) =(ЛЕВСИМВ(A1;ПОИСК(&amp;quot; *&amp;quot;;A1)-1)&amp;amp;&amp;quot; &amp;quot;&amp;amp;ПСТР(A1;ПОИСК(&amp;quot; *&amp;quot;;A1)+1;1)&amp;amp;&amp;quot;.</description><content type="html"><![CDATA[<p>Когда нужно оформить список работников отдела для поощрения или отчёт о работе менеджеров, многие используют Microsoft Excel. А если задача чуть сложнее простого перечисления фамилий в столбик, то постоянно возникает вопрос «Как в экселе сделать что-то».</p>
<p>За время работы у меня собралось несколько полезных формул для обработки ячеек с ФИО и мобильными телефонами, которые постоянно находят своё применение.</p>
<h3 id="как-в-экселе">Как в Экселе</h3>
<ul>
<li><strong>…сократить ФИО до инициалов (Фамилия И.О.)</strong>  <br>
<code>=(ЛЕВСИМВ(A1;ПОИСК(&quot; *&quot;;A1)-1)&amp;&quot; &quot;&amp;ПСТР(A1;ПОИСК(&quot; *&quot;;A1)+1;1)&amp;&quot;.&quot;&amp;ПСТР(A1;ПОИСК(&quot; *&quot;;A1;ПОИСК(&quot; *&quot;;A1)+1)+1;1)&amp;&quot;.&quot;)</code></li>
<li><strong>…переставить первое слово в ячейке в конец (ФИО → ИОФ)</strong>  <br>
<code>=СЖПРОБЕЛЫ(ПРАВСИМВ(A1;ДЛСТР(A1)-НАЙТИ(&quot; &quot;;A1))&amp;&quot; &quot;&amp;ЛЕВСИМВ(A1;НАЙТИ(&quot; &quot;;A1)))</code></li>
<li><strong>…оставить 1 слово с начала строки (Фамилия)</strong>  <br>
<code>=ЛЕВСИМВ(A1;ПОИСК(&quot; &quot;;A1)-1)</code></li>
<li><strong>…оставить 2 слова с начала строки (Фамилия Имя или Имя Отчество)</strong>  <br>
<code>=ЛЕВСИМВ(A1;ПОИСК(&quot; &quot;;A1;ПОИСК(&quot; &quot;;A1)+1)-1)</code></li>
<li><strong>…расставить дефисы в десятизначном телефонном номере (89991234567 → 8-999-123-45-67)</strong>  <br>
<code>=ЛЕВСИМВ(A2;1)&amp;&quot;-&quot;&amp;ЛЕВСИМВ(ПРАВСИМВ(A2;10);3)&amp;&quot;-&quot;&amp;ЛЕВСИМВ(ПРАВСИМВ(A2;7);3)&amp;&quot;-&quot;&amp;ЛЕВСИМВ(ПРАВСИМВ(A2;4);2)&amp;&quot;-&quot;&amp;ЛЕВСИМВ(ПРАВСИМВ(A2;2);2)</code></li>
</ul>
<p><a href="https://cloud.devmem.ru/s/e3tiCgJgP6eXKEz/download/kak-v-eksele-primer.xlsx">Скачать таблицу с примерами</a></p>
]]></content></item></channel></rss>