部落格

  • MySQL系列:一句SQL,MySQL是怎麼工作的?

    MySQL系列:一句SQL,MySQL是怎麼工作的?

    對於MySQL而言,其實分為客戶端與服務端。

    • 服務端,就是MySQL應用,當我們使用net start mysql命令啟動的服務,其實就是啟動了MySQL的服務端。

    • 客戶端,負責發送請求到服務端並從服務端獲取數據,客戶端可以有多種形式,可以是我們通過mysql -uroot -p1234打開的黑窗口,也可以是我們使用的Nativecat、SQLyog等數據庫連接工具,甚至我們的程序,也可以稱作MySQL的客戶端。

    而當我們在mysql窗口或者數據庫連接工具中輸入一句sql后,我們就可以獲取到想要的數據,這中間MySQL到底是怎麼工作的呢?

    在我們執行SQL后,例如一句簡單的select * from user where name = ‘yanger’,客戶端發送請求到服務端,請求到達Server層,會經過連接器、查詢緩存、分析器、優化器、執行器等,最終通過存儲引擎從文件系統獲取數據或者插入數據到文件系統。

    連接器

    在客戶端程序發起連接的時候,需要攜帶主機信息、用戶名、密碼,服務器程序會對客戶端程序提供的這些信息進行認證,如果認證失敗,服務器程序會拒絕連接。

    連接命令大家都比較熟悉。

    mysql -h$ip -P$port -u$user -p

    輸完命令之後,需要繼續輸入密碼,密碼也可以直接跟在 -p 後面,但這樣可能會導致你的密碼泄露,如果你連的是生產服務器,強烈建議你不要這麼做。

    MySQL採用TCP作為服務器和客戶端之間的網絡通信協議,完成 TCP 握手后,連接器主要做密碼校驗和權限獲取。

    • 如果用戶名或密碼不對,你就會收到一個”Access denied for user”的錯誤

    • 如果用戶名密碼認證通過,連接器會到權限表裡面查出你擁有的權限。之後,這個連接裏面的權限判斷邏輯,都將依賴於此時讀到的權限

    MySQL的默認連接是8小時,由參數 wait_timeout 控制的,如果超過這個時間不使用,會自動斷開,並在之後的操作中,拋出Lost connection to MySQL server during query的錯誤。

    查詢緩存

    針對於查詢語句,MySQL 拿到一個查詢請求后,會先到查詢緩存看看,之前是不是執行過這條語句,之前執行過的語句及其結果可能會以 key-value 對的形式,被直接緩存在內存中。如果命中緩存,將直接返回結果。如果不在查詢緩存中,就會繼續後面的執行階段。執行完成后,執行結果會被存入查詢緩存中。

    針對於更新語句,包含插入刪除語句,MySQL 收到更新請求時,會把查詢緩存中該表相關的緩存數據全部清空。

    我們可以看到,只要有更新,緩存就會失效,而對於正常的業務,更新其實是比較頻繁的,也就是說,其實MySQL的查詢緩存命中率並不會很高,所以建議一般不到開啟。

    可以通過設置 query_cache_type 為 DEMAND 來關閉查詢緩存功能。而事實上,在 MySQL 8.0 版本,更是直接移除了查詢緩存這一個功能。

    分析器

    MySQL 首先需要對SQL語句進行分析,分析過程本質上算是一個編譯過程,涉及詞法解析、語法分析、語義分析等階段,通過分析MySQL知道自己要做什麼。

    如果語句不對,就會收到“You have an error in your SQL syntax”的錯誤提醒,一般語法錯誤會提示第一個出現錯誤的位置,所以你要關注的是緊接“use near”的內容。

    優化器

    面對分析器拿到的結果,MySQL會做一些優化處理,例如在表裡面有多個索引的時候,決定使用哪個索引,或者在一個語句有多表關聯(join)的時候,決定各個表的連接順序。

    優化的結果就是生成一個執行計劃,這個執行計劃表明了應該使用哪些索引進行查詢,表之間的連接順序是啥樣的。我們可以使用EXPLAIN語句來查看某個語句的執行計劃。

    這裏\G在命令窗口無法一行時,可以豎著展示結果,方便查看。

    執行器

    經過了分析器和優化器,就正式進行執行階段了,不過執行之前,需要做權限驗證,如果權限不足,就會拋出權限的錯誤。其實在查詢緩存的時候,一樣也會進行權限校驗。

    如果通過驗證,執行器就打開表繼續執行。打開表的時候,執行器就會根據表的引擎定義,去使用這個引擎提供的接口。

    存儲引擎

    MySQL支持非常多種存儲引擎,常用的是InnoDB和MyISAM,MySQL的默認存儲引擎是InnoDB。

    假如我們選擇是InnoDB引擎,對於查詢,那InnoDB 會取這個表的第一行來進行判斷是不是符合要求,符合則存在結果集中,否則繼續進行下一行,直到該表的最後一行。

    然後存儲引擎將結果返回給執行器, 執行器拿着結果返回給客戶端,這樣一句SQL就執行完成了。

    本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※想知道網站建置網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計後台網頁設計

    ※不管是台北網頁設計公司台中網頁設計公司,全省皆有專員為您服務

    ※Google地圖已可更新顯示潭子電動車充電站設置地點!!

    ※帶您來看台北網站建置台北網頁設計,各種案例分享

  • Abp vNext 自定義 Ef Core 倉儲引發異常

    Abp vNext 自定義 Ef Core 倉儲引發異常

    問題

    在使用自定義 Ef Core 倉儲和 ABP vNext 注入的默認倉儲時,通過兩個 Repository 進行 Join 操作,提示 Cannot use multiple DbContext instances within a single query execution. Ensure the query uses a single context instance. 。這個異常信息翻譯成中文的大概意思就是,你不能使用兩個 DbContext 裏面的 DbSet 進行 Join 查詢。

    如果將自定義倉儲改為 IRepository<TEntity,TKey> 進行注入,是可以與 _courseRepostory 進行關聯查詢的。

    我在 XXXEntityFrameworkCoreModule 的配置,以及自定義倉儲 EfCoreStudentRepository 代碼如下。

    XXXEntityFrameworkCoreModule 代碼:

    public class XXXEntityFrameworkCoreModule : AbpModule
    {
        public override void ConfigureServices(ServiceConfigurationContext context)
        {
            context.Services.AddAbpDbContext<XXXDbContext>(op =>
            {
                op.AddDefaultRepositories();
            });
            
            Configure<AbpDbContextOptions>(op => op.UsePostgreSql());
        }
    }

    EfCoreStudentRepository 代碼:

    public class EfCoreStudentRepository : EfCoreRepository<IXXXDbContext, Student, long>, IStudentRepository
    {
        public EfCoreStudentRepository(IDbContextProvider<IXXXDbContext> dbContextProvider) : base(dbContextProvider)
        {
        }
    
        public Task<int> GetCountWithStudentlIdAsync(long studentId)
        {
            return DbSet.CountAsync(x=>x.studentId == studentId);
        }
    }

    原因

    原因在異常信息已經說得十分清楚了,這裏我們需要了解兩個問題。

    1. 什麼原因導致兩個倉儲內部的 DbContext 不一致?
    2. 為什麼 ABP vNext 自己實現的倉儲能夠進行關聯查詢呢?

    首先我們得知道,倉儲內部的 DbContext是怎麼獲取的。我們的自定義倉儲都會繼承 EfCoreRepository ,而這個倉儲是實現了 IQuerable<T> 接口的,最終它會通過一個 IDbContextProvider<TDbContext> 獲得一個可用的 DbContext

    public class EfCoreRepository<TDbContext, TEntity> : RepositoryBase<TEntity>, IEfCoreRepository<TEntity>
        where TDbContext : IEfCoreDbContext
        where TEntity : class, IEntity
    {
        public virtual DbSet<TEntity> DbSet => DbContext.Set<TEntity>();
    
        DbContext IEfCoreRepository<TEntity>.DbContext => DbContext.As<DbContext>();
    
        // 這裏可以看到,是通過 IDbContextProvider 來獲得 DbContext 的。
        protected virtual TDbContext DbContext => _dbContextProvider.GetDbContext();
    
        protected virtual AbpEntityOptions<TEntity> AbpEntityOptions => _entityOptionsLazy.Value;
    
        private readonly IDbContextProvider<TDbContext> _dbContextProvider;
        private readonly Lazy<AbpEntityOptions<TEntity>> _entityOptionsLazy;
    
        // ... 其他代碼。
    }

    下面就是 IDbContextProvider<TDbContext> 內部的核心代碼:

    public class UnitOfWorkDbContextProvider<TDbContext> : IDbContextProvider<TDbContext> where TDbContext : IEfCoreDbContext
    {
        private readonly IUnitOfWorkManager _unitOfWorkManager;
        private readonly IConnectionStringResolver _connectionStringResolver;
    
        // ... 其他代碼。
    
        public TDbContext GetDbContext()
        {
            var unitOfWork = _unitOfWorkManager.Current;
            if (unitOfWork == null)
            {
                throw new AbpException("A DbContext can only be created inside a unit of work!");
            }
    
            var connectionStringName = ConnectionStringNameAttribute.GetConnStringName<TDbContext>();
            var connectionString = _connectionStringResolver.Resolve(connectionStringName);
    
            // 會構造一個 Key,而這個 Key 剛好是泛型類型的 FullName。
            var dbContextKey = $"{typeof(TDbContext).FullName}_{connectionString}";
    
            // 內部是從一個字典當中,根據 dbContextKey 獲取 DbContext。如果不存在的話則調用工廠方法創建一個新的 DbContext。
            var databaseApi = unitOfWork.GetOrAddDatabaseApi(
                dbContextKey,
                () => new EfCoreDatabaseApi<TDbContext>(
                    CreateDbContext(unitOfWork, connectionStringName, connectionString)
                ));
    
            return ((EfCoreDatabaseApi<TDbContext>)databaseApi).DbContext;
        }
    
        // ... 其他代碼。
    }

    通過以上代碼我們就可以知道,ABP vNext 在倉儲的內部是通過 IDbContextProvider<TDbContext> 中的 TDbContext 泛型,來確定是否構建一個新的 DbContext 對象。

    不論是 ABP vNext 針對 IRepository<TEntity,TKey> ,還是我們自己實現的自定義倉儲,它們最終的實現都是基於 EfCoreRepository<TDbContext,TEntity,TKey> 的。而我們 IDbContextProvider<TDbContext> 的泛型,也是這個倉儲基類提供的,後者的 TDbContext 就是前者的泛型參數。

    所以當我們在模塊添加 DbContext 的過城中,只要調用了 AddDefaultRepositories() 方法,ABP vNext 就會遍歷你提供的 TDbContext 所定義的實體,然後為這些實體建立默認的倉儲。

    在注入倉儲的時候,找到了獲得默認倉儲實現類型的方法,可以看到這裏它使用的是 DefaultRepositoryDbContextType 作為默認的 TDbContext 類型。

    protected virtual Type GetDefaultRepositoryImplementationType(Type entityType)
    {
        var primaryKeyType = EntityHelper.FindPrimaryKeyType(entityType);
    
        // 重點在於構造倉儲類型時,傳遞的 Options.DefaultRepositoryDbContextType 參數,這個參數就是後面 EfCoreRepository 的 TDbContext 泛型。
        if (primaryKeyType == null)
        {
            return Options.SpecifiedDefaultRepositoryTypes
                ? Options.DefaultRepositoryImplementationTypeWithoutKey.MakeGenericType(entityType)
                : GetRepositoryType(Options.DefaultRepositoryDbContextType, entityType);
        }
    
        return Options.SpecifiedDefaultRepositoryTypes
            ? Options.DefaultRepositoryImplementationType.MakeGenericType(entityType, primaryKeyType)
            : GetRepositoryType(Options.DefaultRepositoryDbContextType, entityType, primaryKeyType);
    }

    最後我發現這個就是在模塊調用 AddAbpContext<TDbContext> 所提供的泛型參數。

    public abstract class AbpCommonDbContextRegistrationOptions : IAbpCommonDbContextRegistrationOptionsBuilder
    {
        // ... 其他代碼
    
        protected AbpCommonDbContextRegistrationOptions(Type originalDbContextType, IServiceCollection services)
        {
            OriginalDbContextType = originalDbContextType;
            Services = services;
            DefaultRepositoryDbContextType = originalDbContextType;
            CustomRepositories = new Dictionary<Type, Type>();
            ReplacedDbContextTypes = new List<Type>();
        }
    
        // ... 其他代碼
    }
    
    public class AbpDbContextRegistrationOptions : AbpCommonDbContextRegistrationOptions, IAbpDbContextRegistrationOptionsBuilder
    {
        public Dictionary<Type, object> AbpEntityOptions { get; }
    
        public AbpDbContextRegistrationOptions(Type originalDbContextType, IServiceCollection services)
            : base(originalDbContextType, services) // 之類調用的就是上面的構造方法。
        {
            AbpEntityOptions = new Dictionary<Type, object>();
        }
    }
    
    public static class AbpEfCoreServiceCollectionExtensions
    {
        public static IServiceCollection AddAbpDbContext<TDbContext>(
            this IServiceCollection services, 
            Action<IAbpDbContextRegistrationOptionsBuilder> optionsBuilder = null)
            where TDbContext : AbpDbContext<TDbContext>
        {
            // ... 其他代碼。
            
            var options = new AbpDbContextRegistrationOptions(typeof(TDbContext), services);
    
            // ... 其他代碼。
    
            return services;
        }
    }

    所以,我們的默認倉儲的 dbContextKeyXXXDbContext,我們的自定義倉儲繼承 EfCoreRepository<IXXXDbContext,TEntity,TKey> ,所以它的 dbContextKey 就是 IXXXDbContext 。所以自定義倉儲獲取到的 DbContext 就與自定義倉儲的不一致了,從而提示上述異常。

    解決

    找到自定自定義倉儲的定義,修改它 EfCoreReposiotry<TDbContext,TEntity,TKey>TDbContext 泛型參數,變更為 XXXDbContext 即可。

    public class EfCoreStudentRepository : EfCoreRepository<XXXDbContext, Student, long>, IStudentRepository
    {
        public EfCoreStudentRepository(IDbContextProvider<XXXDbContext> dbContextProvider) : base(dbContextProvider)
        {
        }
    
        public Task<int> GetCountWithStudentlIdAsync(long studentId)
        {
            return DbSet.CountAsync(x=>x.studentId == studentId);
        }
    }

    本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

    ※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

    ※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

    南投搬家前需注意的眉眉角角,別等搬了再說!

  • 003.Kubernetes二進制部署準備

    003.Kubernetes二進制部署準備

    一 前置準備

    1.1 前置條件

    相應的充足資源的Linux服務器;

    設置相應的主機名,參考命令:

     1 hostnamectl set-hostname k8smaster

    Mac及UUID唯一;

    若未關閉防火牆則建議放通相應端口,如下:

    Master節點——






    規則

    方向

    端口範圍

    作用

    使用者

    TCP

    Inbound

    6443*

    Kubernetes API server

    All

    TCP

    Inbound

    2379-2380

    etcd server client API

    kube-apiserver, etcd

    TCP

    Inbound

    10250

    Kubelet API

    Self, Control plane

    TCP

    Inbound

    10251

    kube-scheduler

    Self

    TCP

    Inbound

    10252

    kube-controller-manager

    Self

    Worker 節點——

    規則

    方向

    端口範圍

    作用

    使用者

    TCP

    Inbound

    10250

    Kubelet API

    Self, Control plane

    TCP

    Inbound

    30000-32767

    NodePort Services**

    All


    其他更多前置準備見:

    二 主要組件

    2.1 核心組件

    • etcd:保存了整個集群的狀態;
    • apiserver:提供了資源操作的唯一入口,並提供認證、授權、訪問控制、API註冊和發現等機制;
    • controller manager:負責維護集群的狀態,比如故障檢測、自動擴展、滾動更新等;
    • scheduler:負責資源的調度,按照預定的調度策略將Pod調度到相應的機器上;
    • kubelet:負責維護容器的生命周期,同時也負責Volume(CVI)和網絡(CNI)的管理;
    • Container runtime:負責鏡像管理以及Pod和容器的真正運行(CRI);
    • kube-proxy:負責為Service提供cluster內部的服務發現和負載均衡。

    2.2 非核心組件

    • kube-dns:負責為整個集群提供DNS服務;
    • Ingress Controller:為服務提供外網入口;
    • Heapster:提供資源監控;
    • Dashboard:提供GUI;
    • Federation:集群聯邦提供跨可用區的集群;
    • Fluentd-elasticsearch:提供集群日誌採集、存儲與查詢。

    延伸1:對master節點服務組件的理解:

    Master節點上面主要由四個模塊組成:APIServer,schedule,controller-manager,etcd。

    APIServer: APIServer負責對外提供RESTful的kubernetes API的服務,它是系統管理指令的統一接口,任何對資源的增刪該查都要交給APIServer處理后再交給etcd,如架構圖中所示,kubectl(Kubernetes提供的客戶端工具,該工具內部就是對Kubernetes API的調用)是直接和APIServer交互的。

    schedule: schedule負責調度Pod到合適的Node上,如果把scheduler看成一個黑匣子,那麼它的輸入是pod和由多個Node組成的列表,輸出是Pod和一個Node的綁定,即將這個pod部署到這個Node上。Kubernetes目前提供了調度算法,但是同樣也保留了接口,用戶可以根據自己的需求定義自己的調度算法。

    controller manager: 如果APIServer做的是前台的工作的話,那麼controller manager就是負責後台的。每一個資源都對應一個控制器。而control manager就是負責管理這些控制器的,比如我們通過APIServer創建了一個Pod,當這個Pod創建成功后,APIServer的任務就算完成了。而後面保證Pod的狀態始終和我們預期的一樣的重任就由controller manager去保證了。

    etcd:etcd是一個高可用的鍵值存儲系統,kubernetes使用它來存儲各個資源的狀態,從而實現了Restful的API。

    延伸2:對master節點服務組件的理解:

    每個Node節點主要由三個模板組成:kubelet、kube-proxy、runtime。

    runtime:runtime指的是容器運行環境,目前Kubernetes支持docker和rkt兩種容器。

    kube-proxy: 該模塊實現了kubernetes中的服務發現和反向代理功能。kube-proxy支持TCP和UDP連接轉發,默認基於Round Robin算法將客戶端流量轉發到與service對應的一組後端pod。服務發現方面,kube-proxy使用etcd的watch機制,監控集群中service和endpoint對象數據的動態變化,並且維護一個service到endpoint的映射關係,從而保證了後端pod的IP變化不會對訪問者造成影響。另外,kube-proxy還支持session affinity。

    kublet:kublet是Master在每個Node節點上面的agent,是Node節點上面最重要的模塊,它負責維護和管理該Node上的所有容器,但是如果容器不是通過kubernetes創建的,它並不會管理。本質上,它負責使Pod的運行狀態與期望的狀態一致。

    三 部署規劃

    3.1 節點規劃

    節點

    IP

    類型

    運行服務

    k8smaster01 172.24.8.71 Kubernetes master節點 docker、etcd、kube-apiserver、kube-scheduler、kube-controller-manager、kubectl、kubelet、kube-nginx、flannel
    k8smaster02 172.24.8.72 Kubernetes master節點 docker、etcd、kube-apiserver、kube-scheduler、kube-controller-manager、kubectl、 kubelet、kube-nginx、flannel
    k8smaster03 172.24.8.73 Kubernetes master節點 docker、etcd、kube-apiserver、kube-scheduler、kube-controller-manager、kubectl、 kubelet、kube-nginx、flannel
    k8snode01 172.24.8.74 Kubernetes node節點1 docker、etcd、kubelet、proxy、flannel
    k8snode03 172.24.8.75 Kubernetes node節點2 docker、etcd、kubelet、proxy、flannel

    提示:本實驗使用三節點master部署,從而實現master的高可用。

    3.2 組件及版本

    • Kubernetes 1.14.2
    • Docker 18.09.6-ce
    • Etcd 3.3.13
    • Flanneld 0.11.0
    • 插件:
      • Coredns
      • Dashboard
      • Metrics-server
      • EFK (elasticsearch、fluentd、kibana)
    • 鏡像倉庫:
      • docker registry
      • harbor

    3.3 組件策略

    kube-apiserver:

    • 使用節點本地 nginx 4 層透明代理實現高可用;
    • 關閉非安全端口 8080 和匿名訪問;
    • 在安全端口 6443 接收 https 請求;
    • 嚴格的認證和授權策略 (x509、token、RBAC);
    • 開啟 bootstrap token 認證,支持 kubelet TLS bootstrapping;
    • 使用 https 訪問 kubelet、etcd,加密通信;

    kube-controller-manager:

    • 3 節點高可用;
    • 關閉非安全端口,在安全端口 10252 接收 https 請求;
    • 使用 kubeconfig 訪問 apiserver 的安全端口;
    • 自動 approve kubelet 證書籤名請求 (CSR),證書過期后自動輪轉;
    • 各 controller 使用自己的 ServiceAccount 訪問 apiserver;

    kube-scheduler:

    • 3 節點高可用;
    • 使用 kubeconfig 訪問 apiserver 的安全端口;

    kubelet:

    • 使用 kubeadm 動態創建 bootstrap token,而不是在 apiserver 中靜態配置;
    • 使用 TLS bootstrap 機制自動生成 client 和 server 證書,過期后自動輪轉;
    • 在 KubeletConfiguration 類型的 JSON 文件配置主要參數;
    • 關閉只讀端口,在安全端口 10250 接收 https 請求,對請求進行認證和授權,拒絕匿名訪問和非授權訪問;
    • 使用 kubeconfig 訪問 apiserver 的安全端口;

    kube-proxy:

    • 使用 kubeconfig 訪問 apiserver 的安全端口;
    • 在 KubeProxyConfiguration 類型的 JSON 文件配置主要參數;
    • 使用 ipvs 代理模式;

    集群插件:

    • DNS:使用功能、性能更好的 coredns;
    • Dashboard:支持登錄認證;
    • Metric:metrics-server,使用 https 訪問 kubelet 安全端口;
    • Log:Elasticsearch、Fluend、Kibana;
    • Registry 鏡像庫:docker-registry、harbor。

    四 其他準備

    4.1 手動添加解析

    注意:以下4.1至4.7步驟可通過如下腳本快速實現:

      1 [root@k8smaster01 ~]# vi k8sinit.sh
      2 # Modify Author: xhy
      3 # Modify Date: 2019-06-23 22:19
      4 # Version:
      5 #***************************************************************#
      6 # Initialize the machine. This needs to be executed on every machine.
      7 
      8 # Add host domain name.
      9 cat >> /etc/hosts << EOF
     10 172.24.8.71 k8smaster01
     11 172.24.8.72 k8smaster02
     12 172.24.8.73 k8smaster03
     13 172.24.8.74 k8snode01
     14 172.24.8.75 k8snode02
     15 EOF
     16 
     17 # Add docker user
     18 useradd -m docker
     19 
     20 # Disable the SELinux.
     21 sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config
     22 
     23 # Turn off and disable the firewalld.
     24 systemctl stop firewalld
     25 systemctl disable firewalld
     26 
     27 # Modify related kernel parameters & Disable the swap.
     28 cat > /etc/sysctl.d/k8s.conf << EOF
     29 net.ipv4.ip_forward = 1
     30 net.bridge.bridge-nf-call-ip6tables = 1
     31 net.bridge.bridge-nf-call-iptables = 1
     32 net.ipv4.tcp_tw_recycle = 0
     33 vm.swappiness = 0
     34 vm.overcommit_memory = 1
     35 vm.panic_on_oom = 0
     36 net.ipv6.conf.all.disable_ipv6 = 1
     37 EOF
     38 sysctl -p /etc/sysctl.d/k8s.conf >&/dev/null
     39 swapoff -a
     40 sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
     41 modprobe br_netfilter
     42 
     43 # Add ipvs modules
     44 cat > /etc/sysconfig/modules/ipvs.modules <<EOF
     45 #!/bin/bash
     46 modprobe -- ip_vs
     47 modprobe -- ip_vs_rr
     48 modprobe -- ip_vs_wrr
     49 modprobe -- ip_vs_sh
     50 modprobe -- nf_conntrack_ipv4
     51 EOF
     52 chmod 755 /etc/sysconfig/modules/ipvs.modules
     53 bash /etc/sysconfig/modules/ipvs.modules
     54 
     55 # Install rpm
     56 yum install -y conntrack ntpdate ntp ipvsadm ipset jq iptables curl sysstat libseccomp wget
     57 
     58 # Create k8s directory $$ Add system PATH
     59 mkdir -p  /opt/k8s/{bin,work} /etc/{kubernetes,etcd}/cert
     60 echo 'PATH=/opt/k8s/bin:$PATH' >>/root/.bashrc
     61 source /root/.bashrc
     62 
     63 # Reboot the machine.
     64 reboot
      1 [root@k8smaster01 ~]# cat <<EOF >> /etc/hosts
      2 172.24.8.71 k8smaster01
      3 172.24.8.72 k8smaster02
      4 172.24.8.73 k8smaster03
      5 172.24.8.74 k8snode01
      6 172.24.8.75 k8snode02
      7 EOF

    提示:所有節點均建議如上操作。

    4.2 添加docker賬戶

      1 [root@k8smaster01 ~]# useradd -m docker

    提示:所有節點均建議如上操作。

    4.3 關閉SELinux

      1 [root@k8smaster01 ~]# setenforce 0
      2 [root@k8smaster01 ~]# sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config

    4.4 修正iptables

      1 [root@k8smaster01 ~]# systemctl stop firewalld
      2 [root@k8smaster01 ~]# systemctl disable firewalld			#關閉防火牆
      3 [root@k8smaster01 ~]# cat <<EOF >> /etc/sysctl.d/k8s.conf
      4 net.bridge.bridge-nf-call-ip6tables = 1
      5 net.bridge.bridge-nf-call-iptables = 1
      6 net.ipv4.ip_forward = 1
      7 EOF
      8 [root@k8smaster01 ~]# modprobe br_netfilter
      9 [root@k8smaster01 ~]# sysctl -p /etc/sysctl.d/k8s.conf

    提示:所有節點均建議如上操作。

    4.5 關閉swap

      1 [root@k8smaster01 ~]# sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
      2 [root@k8smaster01 ~]# echo "vm.swappiness = 0" >> /etc/sysctl.d/k8s.conf	#禁止使用 swap 空間,只有當系統 OOM 時才允許使用它
      3 [root@k8smaster01 ~]# sysctl -p /etc/sysctl.d/k8s.conf

    4.6 其他調整

      1 [root@k8smaster01 ~]# cat <<EOF >> /etc/sysctl.d/k8s.conf
      2 vm.overcommit_memory = 1						# 不檢查物理內存是否夠用
      3 vm.panic_on_oom = 0							# 開啟 OOM
      4 net.ipv6.conf.all.disable_ipv6 = 1					# 關閉 IPV6
      5 EOF
      6 [root@k8smaster01 ~]# sysctl -p /etc/sysctl.d/k8s.conf
      7 [root@k8smaster01 ~]# mkdir -p  /opt/k8s/{bin,work} /etc/{kubernetes,etcd}/cert	#創建相應目錄
      8 [root@k8smaster01 ~]# yum install -y conntrack ntpdate ntp ipvsadm ipset jq iptables curl sysstat libseccomp wget

    提示:必須關閉 tcp_tw_recycle,否則和 NAT 衝突,會導致服務不通;

    關閉 IPV6,防止觸發 docker BUG。

    4.7 加載IPVS

    pod的負載均衡是用kube-proxy來實現的,實現方式有兩種,一種是默認的iptables,一種是ipvs,相對iptables,ipvs有更好的性能。且當前ipvs已經加入到了內核的主幹。

    為kube-proxy開啟ipvs的前提需要加載以下的內核模塊:

    • ip_vs
    • ip_vs_rr
    • ip_vs_wrr
    • ip_vs_sh
    • nf_conntrack_ipv4
      1 [root@k8smaster01 ~]# cat > /etc/sysconfig/modules/ipvs.modules <<EOF
      2 #!/bin/bash
      3 modprobe -- ip_vs
      4 modprobe -- ip_vs_rr
      5 modprobe -- ip_vs_wrr
      6 modprobe -- ip_vs_sh
      7 modprobe -- nf_conntrack_ipv4
      8 EOF
      9 [root@k8smaster01 ~]# chmod 755 /etc/sysconfig/modules/ipvs.modules
     10 [root@k8smaster01 ~]# bash /etc/sysconfig/modules/ipvs.modules
     11 [root@k8smaster01 ~]# lsmod | grep -e ip_vs -e nf_conntrack_ipv4
     12 [root@k8smaster01 ~]# yum -y install ipvsadm

    提示:所有節點均建議如上操作。

    為了更好的管理和查看ipvs,可安裝相應的管理工具《002.LVS管理工具的安裝與使用》。

    五 環境準備

    5.1 配置免秘鑰

    為了更方便遠程分發文件和執行命令,本實驗配置master節點到其它節點的 ssh 信任關係。

      1 [root@k8smaster01 ~]# ssh-keygen -f ~/.ssh/id_rsa -N ''
      2 [root@k8smaster01 ~]# ssh-copy-id -i ~/.ssh/id_rsa.pub root@k8smaster01
      3 [root@k8smaster01 ~]# ssh-copy-id -i ~/.ssh/id_rsa.pub root@k8smaster02
      4 [root@k8smaster01 ~]# ssh-copy-id -i ~/.ssh/id_rsa.pub root@k8smaster03
      5 [root@k8smaster01 ~]# ssh-copy-id -i ~/.ssh/id_rsa.pub root@k8snode01
      6 [root@k8smaster01 ~]# ssh-copy-id -i ~/.ssh/id_rsa.pub root@k8snode02

    提示:此操作僅需要在master節點操作。

    5.2 分發集群配置參數腳本

    後續使用的環境變量都定義在文件 environment.sh 中,同時拷貝到所有節點的 /opt/k8s/bin 目錄:

      1 #!/usr/bin/bash
      2 
      3 # 生成 EncryptionConfig 所需的加密 key
      4 export ENCRYPTION_KEY=$(head -c 32 /dev/urandom | base64)
      5 
      6 # 集群 MASTER 機器 IP 數組
      7 export MASTER_IPS=(172.24.8.71 172.24.8.72 172.24.8.73)
      8 
      9 # 集群 MASTER IP 對應的主機名數組
     10 export MASTER_NAMES=(k8smaster01 k8smaster02 k8smaster03)
     11 
     12 # 集群 NODE 機器 IP 數組
     13 export NODE_IPS=(172.24.8.74 172.24.8.75)
     14 
     15 # 集群 NODE IP 對應的主機名數組
     16 export NODE_NAMES=(k8snode01 k8snode02)
     17 
     18 # 集群所有機器 IP 數組
     19 export ALL_IPS=(172.24.8.71 172.24.8.72 172.24.8.73 172.24.8.74 172.24.8.75)
     20 
     21 # 集群所有IP 對應的主機名數組
     22 export ALL_NAMES=(k8smaster01 k8smaster02 k8smaster03 k8snode01 k8snode02)
     23 
     24 # etcd 集群服務地址列表
     25 export ETCD_ENDPOINTS="https://172.24.8.71:2379,https://172.24.8.72:2379,https://172.24.8.73:2379"
     26 
     27 # etcd 集群間通信的 IP 和端口
     28 export ETCD_NODES="k8smaster01=https://172.24.8.71:2380,k8smaster02=https://172.24.8.72:2380,k8smaster03=https://172.24.8.73:2380"
     29 
     30 # kube-apiserver 的反向代理(kube-nginx)地址端口
     31 export KUBE_APISERVER="https://127.0.0.1:8443"
     32 
     33 # 節點間互聯網絡接口名稱
     34 export IFACE="eth0"
     35 
     36 # etcd 數據目錄
     37 export ETCD_DATA_DIR="/data/k8s/etcd/data"
     38 
     39 # etcd WAL 目錄,建議是 SSD 磁盤分區,或者和 ETCD_DATA_DIR 不同的磁盤分區
     40 export ETCD_WAL_DIR="/data/k8s/etcd/wal"
     41 
     42 # k8s 各組件數據目錄
     43 export K8S_DIR="/data/k8s/k8s"
     44 
     45 # docker 數據目錄
     46 export DOCKER_DIR="/data/k8s/docker"
     47 
     48 ## 以下參數一般不需要修改
     49 
     50 # TLS Bootstrapping 使用的 Token,可以使用命令 head -c 16 /dev/urandom | od -An -t x | tr -d ' ' 生成
     51 BOOTSTRAP_TOKEN="41f7e4ba8b7be874fcff18bf5cf41a7c"
     52 
     53 # 最好使用 當前未用的網段 來定義服務網段和 Pod 網段
     54 
     55 # 服務網段,部署前路由不可達,部署後集群內路由可達(kube-proxy 保證)
     56 SERVICE_CIDR="10.254.0.0/16"
     57 
     58 # Pod 網段,建議 /16 段地址,部署前路由不可達,部署後集群內路由可達(flanneld 保證)
     59 CLUSTER_CIDR="172.30.0.0/16"
     60 
     61 # 服務端口範圍 (NodePort Range)
     62 export NODE_PORT_RANGE="30000-32767"
     63 
     64 # flanneld 網絡配置前綴
     65 export FLANNEL_ETCD_PREFIX="/kubernetes/network"
     66 
     67 # kubernetes 服務 IP (一般是 SERVICE_CIDR 中第一個IP)
     68 export CLUSTER_KUBERNETES_SVC_IP="10.254.0.1"
     69 
     70 # 集群 DNS 服務 IP (從 SERVICE_CIDR 中預分配)
     71 export CLUSTER_DNS_SVC_IP="10.254.0.2"
     72 
     73 # 集群 DNS 域名(末尾不帶點號)
     74 export CLUSTER_DNS_DOMAIN="cluster.local"
     75 
     76 # 將二進制目錄 /opt/k8s/bin 加到 PATH 中
     77 export PATH=/opt/k8s/bin:$PATH
      1 [root@k8smaster01 ~]# source environment.sh
      2 [root@k8smaster01 ~]# for all_ip in ${ALL_IPS[@]}
      3   do
      4     echo ">>> ${all_ip}"
      5     scp environment.sh root@${all_ip}:/opt/k8s/bin/
      6     ssh root@${all_ip} "chmod +x /opt/k8s/bin/*"
      7   done

    本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

    網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

    ※想知道最厲害的台北網頁設計公司推薦台中網頁設計公司推薦專業設計師”嚨底家”!!

  • 科學家發現新型態鈾 恐影響核廢料處理計畫

    環境資訊中心綜合外電;姜唯 編譯;林大利 審校

    本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※帶您來了解什麼是 USB CONNECTOR  ?

    ※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

    ※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

    ※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

    ※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

  • 澳洲野火不止 維州熱浪祭禁火令 擬照辦跨年煙火秀

    摘錄自2019年12月30日中央通訊社報導

    澳洲野火肆虐,重創當地生態環境及空氣品質,已逾26萬人連署,建議取消知名的雪梨跨年煙火秀,以免助長空氣污染,把錢省下來幫助受災農民及消防員等,不過,雪梨市長克洛弗.摩爾(Clover Moore)已煙火秀照舊,且據報導,高達10萬支煙火都已裝船開運,其中有8成來自中國。

    綜合媒體報導,雪梨是全球最早迎接新年的大城市之一,跨年煙火秀更是全球慶祝跨年的重點戲之一,去(2018)年就花了580萬澳元(約1.2億元台幣),今年打算花650萬澳元(約1.36億台幣)來辦跨年煙火秀,但今年正值澳洲發生數十年來最嚴重的野火災難,致農損嚴重,截至目前並未撲滅,致使澳洲民眾在網上連署,建議當局取消今年跨年煙火秀。

    不過當局並不打算取消,女市長摩爾並表示,若是取消,可能重創雪梨商家們,也會毀了數以萬計前來雪梨參加跨年活動人們的計劃。

    即使如此,這場煙火秀是否在最後喊停,還在未定之天,因為,澳洲野火未停,仍有接近100個火場火勢仍未撲滅,雪梨所屬的新南威爾斯省的災情最嚴重,且位於雪梨西南面的巴爾莫勒爾鎮幾乎全毀,許多公路仍然封閉;且產生的空氣污染已經形成有毒煙霧,籠罩雪梨及其他主要城市。

    由於East Gippsland的森林火災不斷升級,加上熱浪來襲,預計今天氣溫可能升高到44度,維多利亞州當局已在昨天(29日)下令,全面撤離Goongerah和Martins Creek地區居民,今天更將全州實行禁火令,嚴禁人們在戶外用火。

    本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※為什麼 USB CONNECTOR 是電子產業重要的元件?

    網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

    ※想要讓你的商品成為最夯、最多人討論的話題?網頁設計公司讓你強力曝光

    ※想知道最厲害的台北網頁設計公司推薦台中網頁設計公司推薦專業設計師”嚨底家”!!

  • 菲擬重啟核電 地震帶問題未解

    摘錄自2019年12月27日自由時報報導

    菲律賓能源部長庫希(Alfonso Cusi)接受英國金融時報訪問表示,為了解決未來可能出現的能源匱乏問題,菲律賓已經與國際原子能總署(IAEA)合作,努力達成聯合國監管機構要求的安全條件,擬重啟已被擱置許久的核電廠計畫。

    菲律賓前獨裁領袖馬可仕擔任總統時,曾在首都馬尼拉附近的巴丹半島建造核電廠,因民眾反彈聲浪,巴丹核電廠計畫於1986年,被時任總統柯拉蓉.艾奎諾擱置。

    菲律賓西邊的南海雖然富含石油與天然氣資源,但因主權爭議使菲國無法開採。庫希表示,菲國需要穩固、可靠、負擔得起的能源,而核能正好符合上述條件。菲國總統杜特蒂今年十月訪問莫斯科時,與俄方簽署合作意向書。庫希說,為重啟核電廠,菲國考慮和南韓合作,也不排除向原始建造商美國西屋電氣尋求協助,但一切都尚未確定。

    評論家指出,巴丹核電廠有雙重風險,它不只選址於環太平洋地震帶,甚至選在一座休眠火山上,核能污染的危險性恐因該地的地質環境而惡化。對此,菲國能源部去年曾發表文章澄清,巴丹核電廠並非選址於火山口,且專家研判,像日本福島震災一樣芮氏規模九的強震,幾乎不可能在菲國發生。

    庫希表示,在所有相關法案通過後,尚需七至八年才能完成核電廠計畫,在這期間,他們也會持續尋找其他可用能源,例如油、煤、天然氣、再生能源等。

    由於核電廠造價不菲,且菲律賓已有其他大型建設延宕,不少分析師懷疑菲國是否有能力執行核電廠計畫。能源諮詢公司伍德麥肯茲(Wood Mackenzie)的亞太研究主管哈伍德(Andrew Harwood)指出,重啟巴丹核電廠需要巨額資金,使用煤與其他再生能源是最便宜且可行方法。

    本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

    ※評比前十大台北網頁設計台北網站設計公司知名案例作品心得分享

    ※智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選

    ※評比南投搬家公司費用收費行情懶人包大公開

  • 全球最長壽黑犀牛 57歲壽終正寢

    摘錄自2019年12月28日中央通訊社綜合報導

    坦尚尼亞保護區管理局指出,據信是全球最長壽的一頭雌黑犀牛昨天(27日)在恩戈羅恩戈羅保護區壽終正寢,享壽57歲。

    恩戈羅恩戈羅保護區管理局(Ngorongoro Conservation Area Authority)28日發表聲說,名為佛斯塔(Fausta)的這頭雌黑犀牛,於12月27日在保護區內據信因自然原因死亡,牠生前絕大部分時間都是在野外生活。

    恩戈羅恩戈羅保護區管理局估計,野生犀牛的壽命介於37到43歲間,圈養犀牛則能活到50歲以上。聲明指出,紀錄顯示,佛斯塔較全球任何其他犀牛都更長壽,在恩戈羅恩戈羅放養超過54年,2016年才移至庇護區。

    聲明又說:「三蘭港大學(University of Dar Es Salaam)一位科學家於1965年首度在恩戈羅恩戈羅火山口發現佛斯塔,當時牠的年齡介於3至4歲間。繼多次遭鬣狗攻擊且嚴重受傷後,牠的健康狀況於2016年開始惡化,我們不得不把牠置於圈養狀態。」

    而全球最長壽的白犀牛,則是55歲的雌南方白犀牛沙納(Sana),於2017年在圈養地法國奇幻星球動物園(La Planete Sauvage Zoological park)死亡。

    本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    台北網頁設計公司這麼多,該如何挑選?? 網頁設計報價省錢懶人包"嚨底家"

    網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

    ※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

    南投搬家費用,距離,噸數怎麼算?達人教你簡易估價知識!

  • 來自衣服與塑袋 英國倫敦微塑料沉積嚴重

    摘錄自2019年12月28日中央通訊社綜合報導

    英國「衛報」報導,有研究發現,城市居民會吸收空氣中傾洩而下的微塑料污染物,目前記錄到微塑料沉積最嚴重的城市為英國倫敦。吸入或吃進細小塑膠微粒對人體健康的衝擊仍不明,專家呼籲有必要即刻研究以評估相關風險。

    這份研究目前只評估4個城市,但4個地方的空氣全都有微塑料的蹤影。科學家相信,由於衣服與包裝袋等微塑料的源頭四處可見,世界每個城市的空氣應都有被微塑料污染。

    這份刊登於「國際環境」(Environment International)期刊的研究指出,每年約新增3.35億公噸原始塑料,大多流入自然環境。

    研究人員在倫敦市中心一棟9層樓的建物屋頂蒐集飄落的微塑料,在全部8個樣本裡都有發現,沉積率從每天每平方公尺575片到1008片不等,且從中確認出15種不同的塑料。大部分的微塑料是壓克力纖維,極可能來自人們的衣服。只有8%是塑膠微粒,當中大部分為聚苯乙烯、聚乙烯,這兩者皆為常用的食品包裝材料。

    倫敦的微塑料沉積率是中國東莞的20倍、法國巴黎的7倍、將近德國漢堡的3倍。研究員目前仍不知道各地沉積率差異的原因,不同的實驗方式有可能是原因之一。

    倫敦空氣裡的微塑料含量震驚了科學家。帶領這項研究的倫敦國王學院(King’s College London)專家萊特(Stephanie Wright)說:「我們發現高含量的微塑料,遠高於先前披露的數據。但世界所有城市應該都會有類似狀況」。

    在倫敦市中心採集到的塑膠微粒介於0.02毫米至0.5毫米之間,這些微粒大到在吸入時會停留在呼吸道,並順著唾液被吞入。更小的粒子會被吸入肺部和血液,對健康造成最大的潛在危害。

    報導指出,交通和工業排放的污染物對人體的嚴重危害眾所皆知,2019年初一份綜合性的全球評估指出,空污可能會損害人體每一個器官,甚至每一個細胞。但目前仍然不知道從空氣吸進、從飲食吃進塑膠微粒對人體的潛在衝擊程度;根據其他研究,人們平均每年吃下至少5萬個塑膠微粒。

    德國「艾佛瑞德維根納極地海洋研究所」(Alfred Wegener Institute for Polar and Marine Research)專家柏格曼(Melanie Bergmann)表示,對微塑料污染潛藏的健康危害進行更多研究非常重要,「我們目前並不知道,吸入人體的微塑料,有多少會滲入肺部深處」。

    萊特說,要想減少微塑料,就要改變使用塑膠及處理塑膠的方式,「你沒有辦法清光它們,所以該是從源頭來遏止了」。

    本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※想知道網站建置網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計後台網頁設計

    ※不管是台北網頁設計公司台中網頁設計公司,全省皆有專員為您服務

    ※Google地圖已可更新顯示潭子電動車充電站設置地點!!

    ※帶您來看台北網站建置台北網頁設計,各種案例分享

  • 非洲豬瘟肆虐 越南求助美國與荷蘭合製疫苗

    摘錄自2019年12月28日中央通訊社報導

    越南非洲豬瘟疫情升溫,嚴重打擊養豬業,造成境內豬肉供應短缺。越南農業機構表示,將與美國與荷蘭合作研製非洲豬瘟疫苗,同時擴大豬肉進口以彌補境內缺口,鼓勵農戶重新養豬。

    越南農業暨農村發展部數據顯示,非洲豬瘟疫情2月爆發以來,全國63省市、667縣、8532個村落淪陷,被迫撲殺染病豬隻約600萬頭,重量約34萬2000噸,占全國豬肉總重量的9%。由於豬肉供給減少,越南各地豬肉價格最近飆漲不斷,創下10年來新高,消費者肉品食用習慣受到影響。豬肉價格飆漲,造成越南12月消費者物價指數(CPI)較11月上漲1.4%,創下9年來新高。

    「線上知識報」新聞網站26日報導,越南農業暨農村發展部部長阮春強(Nguyen Xuan Cuong)受訪表示,越南非洲豬瘟疫苗自主研發工作目前取得了初步進展,未來將與美國與荷蘭合作研製疫苗。

    阮春強表示,美國農業專家明年1月將前來越南,共同合作研發與生產非洲豬瘟疫苗,「在不久的將來,與確保生物安全等措施的同時,我們正在為推動養殖業永續發展創造便利條件」。越南農業機構表示,目前非洲豬瘟疫情逐漸趨緩,因此鼓勵農戶在確保生物安全的情況下重新養豬,推動家禽與其他家畜等養殖業發展,同時加強宣導改變消費者以豬肉為主的肉品食用習慣。

    本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    網頁設計公司推薦更多不同的設計風格,搶佔消費者視覺第一線

    ※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

    ※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

    南投搬家前需注意的眉眉角角,別等搬了再說!

  • 印度市政府開「垃圾餐廳 」 塑膠撿越多 吃得越好

    環境資訊中心綜合外電;姜唯 編譯;林大利 審校

    本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

    網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

    ※想知道最厲害的台北網頁設計公司推薦台中網頁設計公司推薦專業設計師”嚨底家”!!