完全分布式安装hadoop集群

0、安装jdk

1、配置hosts文件

2、建立hadoop运行账号

3、配置ssh免密码登录

4、在namenode上配置hadoop

    4.1、修改hadoop-env.sh文件

    4.2、修改yarn-env.sh文件

    4.3、修改core-site.xml文件

    4.4、修改hdfs-site.xml文件

    4.5、修改mapred-site.xml文件

    4.6、修改yarn-site.xml文件

5、配置masters和slaves文件

6、向各节点复制hadoop

7、格式化namenode

8、启动hadoop

9、用jps检验各后台进程是否成功启动

10、启动yarn

11、启动历史服务器

12、测试wordcount程序

附:SSH原理

 

安装jdk

//将jdk解压到software目录下

tar -xzvf jdk-7u79-linux-x64.tar.gz -C ../software/

//配置jdk的环境变量

[wangqi@node000 ~]$ cd ~

[wangqi@node000 ~]$ ls -al

total 36

drwx------. 4 wangqi wangqi 4096 Dec 21 10:48 .

drwxr-xr-x. 9 root root 4096 Dec 21 09:53 ..

-rw-------. 1 wangqi wangqi 18 Dec 21 09:58 .bash_history

-rw-r--r--. 1 wangqi wangqi 18 Feb 22 2013 .bash_logout

-rw-r--r--. 1 wangqi wangqi 176 Feb 22 2013 .bash_profile

-rw-r--r--. 1 wangqi wangqi 124 Feb 22 2013 .bashrc

drwxrwxr-x. 2 wangqi wangqi 4096 Dec 21 10:39 download

drwxrwxr-x. 3 wangqi wangqi 4096 Dec 21 10:42 software

-rw-------. 1 wangqi wangqi 689 Dec 21 10:48 .viminfo

//在.bash_profile中添加用户环境变量

[wangqi@node000 ~]$ vim .bash_profile

JAVA_HOME=/home/wangqi/software/jdk1.7.0_79

PATH=$JAVA_HOME/bin:$PATH:$HOME/bin

CLASSPATH=.:$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/db.jar:$JAVA_HOME/lib/tools.jar

export JAVA_HOME PATH CLASSPATH

//使环境变量生效

[wangqi@node000 ~]$ source .bash_profile

//验证jdk是否安装成功

[wangqi@node000 ~]$ javac -version

javac 1.7.0_79

配置hosts文件

所有的节点都需要/etc/hosts文件,使彼此之间都能把主机名解析为对应ip。

[wangqi@node000 software]$ sudo vim /etc/hosts

10.254.201.200 node000

10.254.201.201 node001

10.254.201.202 node002

这里我们有三台机器,需要在每台机器的hosts文件中配置主机名和对应的ip,使其可以相互访问。

建立hadoop运行账号

为了安全起见,最好在各个机器上建立专门用于hadoop开发的账号。

[root@node001 home]# useradd wangqi

[root@node001 home]# passwd wangqi

Changing password for user wangqi.

New password:

BAD PASSWORD: it is too short

BAD PASSWORD: is too simple

Retype new password:

passwd: all authentication tokens updated successfully.

ssh配置

在每台机器上都生成公钥私钥。

[wangqi@node000 ~]$ ssh-keygen -t rsa

Generating public/private rsa key pair.

Enter file in which to save the key (/home/wangqi/.ssh/id_rsa):

Created directory '/home/wangqi/.ssh'.

Enter passphrase (empty for no passphrase):

Enter same passphrase again:

Your identification has been saved in /home/wangqi/.ssh/id_rsa.

Your public key has been saved in /home/wangqi/.ssh/id_rsa.pub.

The key fingerprint is:

e3:ca:fb:16:15:6b:c1:90:ab:af:5f:b2:1e:65:e5:ab wangqi@node000

The key's randomart image is:

+--[ RSA 2048]----+

| .+ |

| . + |

| . +. |

| . +o |

| .Soo . |

| ...+ . |

| .+.. . |

| . .o= . |

| =B= E |

+-----------------+

然后把公钥放到授权key中。

[wangqi@node000 ~]$ cd .ssh

[wangqi@node000 .ssh]$ ls

id_rsa id_rsa.pub

[wangqi@node000 .ssh]$ cp id_rsa.pub authrized_keys

[wangqi@node000 .ssh]$ ls

authrized_keys id_rsa id_rsa.pub

最后把各个几点的authorized_keys的内容互相拷贝到对方的此文件中,这样就可以免密码彼此ssh登录。

在namenode上配置hadoop

1)修改hadoop-env.sh文件

[wangqi@node000 ~]$ cd software/hadoop-2.6.0/etc/hadoop/

取消JAVA_HOME注释并做如下修改:

export JAVA_HOME=/home/wangqi/software/jdk1.7.0_79

保存退出。

注:不同版本的hadoop的配置文件所在的位置可能不一样。

2)修改yarn-env.sh文件

vim etc/hadoop/yarn-env.sh

export JAVA_HOME=/home/wangqi/software/jdk1.7.0_79

3)修改core-site.xml文件

<configuration>
        <property>
                <name>fs.default.name</name>
                <value>hdfs://node000:10000</value>
        </property>
        <property>
                <name>hadoop.tmp.dir</name>
                <value>file:///home/wangqi/software/hadoop-2.6.0/tmp</value>
        </property>
</configuration>

注:

1、fs.default.name表示namenode的IP地址和监听端口。namenode与datanode之间的通信就是通过该端口来完成的。

2、hadoop.tmp.dir 表示hadoop的临时文件存储目录

3、hadoop.tmp.dir中指定的tmp文件夹不用自己创建,格式化namenode时会自动创建

4)修改hdfs-site.xml文件

<configuration>
    <property>
        <name>dfs.namenode.secondary.http-address</name>
        <value>node000:40090</value>
        <description>namenode get the newest fsimage via 
dfs.secondary.http-address</description>
    </property>
    <property>
        <name>dfs.namenode.http-address</name>
        <value>node000:40070</value>
        <description>secondary get fsimage and edits via 
dfs.namenode.http-address</description>
    </property>
    <property>
        <name> dfs.namenode.name.dir </name>
        <value>file:///home/wangqi/software/hadoop-2.6.0/hdfs/name</value>
        <description>the place where store the namenode</description>
    </property>
    <property>
        <name> dfs.datanode.data.dir </name>
        <value>file:///home/wangqi/software/hadoop-2.6.0/hdfs/data</value>
        <description>the place where store the datanode</description>
    </property>
    <property>
        <name>dfs.replication</name>
        <value>3</value>
    </property>
</configuration>

注:

1、dfs.namenode.secondary.http-address表示辅助名称节点http服务的地址和端口。

2、dfs.namenode.http-address表示名称节点web ui监听地址和端口。

3、dfs.namenode.name.dir表示名称节点所使用的元数据的保存路径。

4、dfs.datanode.data.dir表示数据节点存储数据块的路径,可以写多块硬盘,逗号分隔。把这些位置分散在每个节点上的所有磁盘上可以实现磁盘I/O平衡,会显著改进磁盘I/O性能。

5、dfs.replication表示hdfs数据块的复制份数,默认3,理论上份数越多跑数速度越快,但是需要的存储空间也更多。因为我们现在是伪分布式,即只有一个节点,因此只能复制一份。

说明:

1、路径应该写成file://的格式。

2、这里配置的dfs.namenode.secondary.http-address和dfs.namenode.http-address都有默认配置,我是因为机器上有其他人已经部署了hadoop,为了防止端口被占用,因此显示指定了。

3、dfs.namenode.name.dir和dfs.datanode.data.dir我们显示指定时,需要保证其中hdfs这一级目录已经创建(name和data这一级目录不用创建,格式化namenode时会自动创建name目录,启动dfs时会自动创建data目录)。

5)修改mapred-site.xml文件

<configuration>
<property>
          <name>mapreduce.framework.name</name>
         <value>yarn</value>
</property>
<property>
         <name>mapreduce.jobtracker.address</name>
           <value>node000:60040</value>
        </property>
<property>
                <name>mapreduce.jobtracker.http.address</name>
                <value>node000:60030</value>
        </property>
        <property>
                <name>mapreduce.jobhistory.address</name>
                <value>node000:60020</value>
        </property>
        <property>
                <name>mapreduce.jobhistory.webapp.address</name>
                <value>node000:60888</value>
        </property>
<property>
<name>yarn.app.mapreduce.am.staging-dir</name>           <value>/tmp/hadoop-yarn/staging</value>
        </property>
        <property>
                <name>mapreduce.jobhistory.done-dir</name>
                <value>${yarn.app.mapreduce.am.staging-dir}/history/done</value>
        </property>
        <property>
                <name>mapreduce.jobhistory.intermediate-done-dir</name>
<value>${yarn.app.mapreduce.am.staging-dir}/history/done_intermediate</value>
        </property>
</configuration>

注:

1、mapreduce.framework.name表示执行mapreduce任务时的运行时框架。

2、mapreduce.jobtracker.address表示jobtracker的ip地址和端口号

2、mapreduce.jobtracker.http.address表示jobtracker的http服务的ip地址和端口号。

3、mapreduce.jobhistory.address表示MapReduce JobHistory服务器进程间通信(IPC)的主机和端口号。

4、mapreduce.jobhistory.webapp.address表示MapReduce JobHistory服务器Web UI 的主机和端口号。

5、yarn.app.mapreduce.am.staging-dir表示提交的job的暂存目录。

6、mapreduce.jobhistory.done-dir表示在什么目录下存放已经运行完的Hadoop作业记录。

7、mapreduce.jobhistory.intermediate-done-dir表示在什么目录下存放正在运行的Hadoop作业记录。

6)修改yarn-site.xml文件

<configuration>
        <property>
               <name>yarn.nodemanager.aux-services</name>
               <value>mapreduce_shuffle</value>
        </property>
        <property>                                                                
           <name>yarn.nodemanager.aux-services.mapreduce.shuffle.class</name>
               <value>org.apache.hadoop.mapred.ShuffleHandler</value>
        </property>
        <property>
               <name>yarn.resourcemanager.address</name>
               <value>node001:9032</value>
       </property>
       <property>
               <name>yarn.resourcemanager.scheduler.address</name>
               <value>node001:9030</value>
       </property>
       <property>
            <name>yarn.resourcemanager.resource-tracker.address</name>
             <value>node001:9031</value>
      </property>
      <property>
              <name>yarn.resourcemanager.admin.address</name>
               <value>node001:9033</value>
       </property>
       <property>
               <name> yarn.resourcemanager.webapp.address </name>
               <value>node001:9088</value>
       </property>
</configuration>

注:

1、yarn.resourcemanager.webapp.address表示RM web应用的http地址和端口。

修改masters和slaves文件

[wangqi@node000 sbin]$ vim ~/software/hadoop-2.6.0/etc/hadoop/masters

node000

[wangqi@node000 sbin]$ vim ~/software/hadoop-2.6.0/etc/hadoop/slaves

node001

node002

注:

1、masters文件中指定的是secondary namenode的主机名,不是namenode

将配置好的hadoop发送到从节点

[wangqi@node000 sbin]$ scp -r ~/software/hadoop-2.6.0/

wangqi@10.254.201.201:~/software/

[wangqi@node000 sbin]$ scp -r ~/software/hadoop-2.6.0/

wangqi@10.254.201.202:~/software/

另外,因为我这边的机器上,其他人已经部署了hadoop,为了防止端口被占用,还需要修改各从节点中的hdfs-site.xml文件。(如果机器上没有其他人部署了hadoop,则省略这步操作)

1)修改从节点201中的hdfs-site.xml文件

将从节点201的hdfs-site.xml文件修改如下:

[wangqi@node001 software]$ vim hadoop-2.6.0/etc/hadoop/hdfs-site.xml

<configuration>
    <property>
        <name>dfs.namenode.secondary.http-address</name>
        <value>node000:40090</value>
        <description>namenode get the newest fsimage via 
dfs.secondary.http-address</description>
    </property>
    <property>
        <name>dfs.namenode.http-address</name>
        <value>node000:40070</value>
        <description>secondary get fsimage and edits via 
dfs.namenode.http-address</description>
    </property>
    <property>
        <name>dfs.name.dir</name>
        <value>file:///home/wangqi/software/hadoop-2.6.0/hdfs/name</value>
        <description>the place where store the namenode</description>
    </property>
    <property>
        <name>dfs.data.dir</name>
        <value>file:///home/wangqi/software/hadoop-2.6.0/hdfs/data</value>
        <description>the place where store the datanode</description>
    </property>
    <property>
        <name>dfs.replication</name>
        <value>3</value>
    </property>
    <property>
        <name>dfs.datanode.address</name>
        <value>node001:60010</value>
    </property>
    <property>
        <name>dfs.datanode.http.address</name>
        <value>node001:60075</value>
    </property>
    <property>
        <name>dfs.datanode.ipc.address</name>
        <value>node001:60020</value>
    </property>
</configuration>

注:

1、dfs.datanode.address表示数据节点传输数据时的地址和端口。

2、dfs.datanode.http.address表示数据节点http服务的地址和端口。

3、dfs.datanode.ipc.address表示数据节点IPC(进程间通信)服务地址和端口。

2)修改从节点202中的hdfs-site.xml文件

对从节点202中hdfs-site.xml文件的修改和上面一样,只是把node001修改成了node002,如下:

<configuration>
    <property>
        <name>dfs.namenode.secondary.http-address</name>
        <value>node000:40090</value>
        <description>namenode get the newest fsimage via 
dfs.secondary.http-address</description>
    </property>
    <property>
        <name>dfs.namenode.http-address</name>
        <value>node000:40070</value>
        <description>secondary get fsimage and edits via 
dfs.namenode.http-address</description>
    </property>
    <property>
        <name>dfs.name.dir</name>
        <value>file:///home/wangqi/software/hadoop-2.6.0/hdfs/name</value>
        <description>the place where store the namenode</description>
    </property>
    <property>
        <name>dfs.data.dir</name>
        <value>file:///home/wangqi/software/hadoop-2.6.0/hdfs/data</value>
        <description>the place where store the datanode</description>
    </property>
    <property>
        <name>dfs.replication</name>
        <value>3</value>
    </property>
    <property>
        <name>dfs.datanode.address</name>
        <value>node002:60010</value>
    </property>
    <property>
        <name>dfs.datanode.http.address</name>
        <value>node002:60075</value>
    </property>
    <property>
        <name>dfs.datanode.ipc.address</name>
        <value>node002:60020</value>
    </property>
</configuration>

格式化分布式文件系统

[wangqi@node000 bin]$ ./hadoop namenode -format

或者

[wangqi@node000 bin]$ ./hdfs namenode -format

15/12/28 12:12:06 INFO common.Storage: Storage directory

/home/wangqi/software/hadoop-2.6.0/hdfs/name has been successfully formatted.

15/12/28 12:12:06 INFO namenode.NNStorageRetentionManager: Going to retain 1 images

with txid >= 0

15/12/28 12:12:06 INFO util.ExitUtil: Exiting with status 0

15/12/28 12:12:06 INFO namenode.NameNode: SHUTDOWN_MSG:

/************************************************************

SHUTDOWN_MSG: Shutting down NameNode at node001/10.254.201.201

************************************************************/

启动hdfs

[wangqi@node000 sbin]$ ./start-dfs.sh

15/12/25 15:51:06 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable

Starting namenodes on [node000]

node000: starting namenode, logging to

/home/wangqi/software/hadoop-2.6.0/logs/hadoop-wangqi-namenode-node000.out

node001: starting datanode, logging to

/home/wangqi/software/hadoop-2.6.0/logs/hadoop-wangqi-datanode-node001.out

node002: starting datanode, logging to

/home/wangqi/software/hadoop-2.6.0/logs/hadoop-wangqi-datanode-node002.out

Starting secondary namenodes [node000]

node000: starting secondarynamenode, logging to

/home/wangqi/software/hadoop-2.6.0/logs/hadoop-wangqi-secondarynamenode-node000.out

15/12/25 15:51:23 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable

检测守护进程启动情况

[wangqi@node000 sbin]$ jps

100266 Jps

99858 NameNode

100092 SecondaryNameNode

[wangqi@node001 software]$ jps

39666 DataNode

39759 Jps

[wangqi@node002 software]$ jps

239950 Jps

239858 DataNode

启动yarn

[wangqi@node000 sbin]$ start-yarn.sh

starting yarn daemons

starting resourcemanager, logging to

/home/wangqi/software/hadoop-2.6.0/logs/yarn-wangqi-resourcemanager-node000.out

node001: starting nodemanager, logging to

/home/wangqi/software/hadoop-2.6.0/logs/yarn-wangqi-nodemanager-node001.out

node002: starting nodemanager, logging to

/home/wangqi/software/hadoop-2.6.0/logs/yarn-wangqi-nodemanager-node002.out

[wangqi@node000 sbin]$ jps

11901 ResourceManager

12176 Jps

11437 NameNode

11663 SecondaryNameNode

[wangqi@node001 hadoop-2.6.0]$ jps

5520 Jps

5166 DataNode

5323 NodeManager

此时hadoop集群已全部部署完成。

在浏览器中输入:http://10.254.201.201:9088/,结果如下:

启动历史服务器

[wangqi@node001 sbin]$ mr-jobhistory-daemon.sh start historyserver

starting historyserver, logging to

/home/wangqi/software/hadoop-2.6.0/logs/mapred-wangqi-historyserver-node001.out

测试WordCount程序

1、在hdfs上创建input目录

[wangqi@node001 input]$ hdfs dfs -mkdir -p /user/wangqi/in

[wangqi@node001 input]$ hdfs dfs -ls -R /

drwxr-xr-x - wangqi supergroup 0 2015-12-28 16:14 /user

drwxr-xr-x - wangqi supergroup 0 2015-12-28 16:14 /user/wangqi

drwxr-xr-x - wangqi supergroup 0 2015-12-28 16:14 /user/wangqi/in

注:一定要创建成/user/wangqi/in(其中wangqi是创建的用户),因为后面执行mapreduce任务时,会在user/wangqi目录下找in目录,否则会报错:

Exception in thread "main" org.apache.hadoop.mapreduce.lib.input.InvalidInputException: Input path does not exist: hdfs://node001:10000/user/wangqi/input

2、在本机上创建input目录,并写入两个文件

[wangqi@node001 ~]$ mkdir input

[wangqi@node001 input]$ echo "hello world" > test1.txt

[wangqi@node001 input]$ echo "hello hadoop" > test2.txt

[wangqi@node001 input]$ cat test1.txt

hello world

[wangqi@node001 input]$ cat test2.txt

hello hadoop

3、将文件上传到hadoop的input目录下

[wangqi@node001 input]$ hdfs dfs -put ./* /user/wangqi/in/

[wangqi@node001 input]$ hdfs dfs -ls -R /

drwxr-xr-x - wangqi supergroup 0 2015-12-28 16:14 /user

drwxr-xr-x - wangqi supergroup 0 2015-12-28 16:14 /user/wangqi

drwxr-xr-x - wangqi supergroup 0 2015-12-28 16:17 /user/wangqi/in

-rw-r--r-- 2 wangqi supergroup 12 2015-12-28 16:17 /user/wangqi/in/test1.txt

-rw-r--r-- 2 wangqi supergroup 13 2015-12-28 16:17 /user/wangqi/in/test2.txt

4、运行示例程序WordCount

[wangqi@node001 input]$ hadoop jar /home/wangqi/software/hadoop-2.6.0/share/hadoop/mapreduce/sources/hadoop-mapreduce-exampls-2.6.0-sources.jar org.apache.hadoop.examples.WordCount in out

15/12/28 16:18:39 INFO client.RMProxy: Connecting to ResourceManager at

node001/10.254.201.201:9032

15/12/28 16:18:40 INFO input.FileInputFormat: Total input paths to process : 2

15/12/28 16:18:40 INFO mapreduce.JobSubmitter: number of splits:2

15/12/28 16:18:40 INFO mapreduce.JobSubmitter: Submitting tokens for job:

job_1451286103870_0007

15/12/28 16:18:40 INFO impl.YarnClientImpl: Submitted application

application_1451286103870_0007

15/12/28 16:18:40 INFO mapreduce.Job: The url to track the job:

http://node001:9088/proxy/application_1451286103870_0007/

15/12/28 16:18:40 INFO mapreduce.Job: Running job: job_1451286103870_0007

15/12/28 16:18:47 INFO mapreduce.Job: Job job_1451286103870_0007 running in uber

mode : false

15/12/28 16:18:47 INFO mapreduce.Job: map 0% reduce 0%

15/12/28 16:18:53 INFO mapreduce.Job: map 100% reduce 0%

15/12/28 16:18:59 INFO mapreduce.Job: map 100% reduce 100%

15/12/28 16:18:59 INFO mapreduce.Job: Job job_1451286103870_0007 completed

successfully

15/12/28 16:19:00 INFO mapreduce.Job: Counters: 49

File System Counters

FILE: Number of bytes read=55

FILE: Number of bytes written=317236

FILE: Number of read operations=0

FILE: Number of large read operations=0

FILE: Number of write operations=0

HDFS: Number of bytes read=245

HDFS: Number of bytes written=25

HDFS: Number of read operations=9

HDFS: Number of large read operations=0

HDFS: Number of write operations=2

Job Counters

Launched map tasks=2

Launched reduce tasks=1

Data-local map tasks=2

Total time spent by all maps in occupied slots (ms)=7461

Total time spent by all reduces in occupied slots (ms)=3882

Total time spent by all map tasks (ms)=7461

Total time spent by all reduce tasks (ms)=3882

Total vcore-seconds taken by all map tasks=7461

Total vcore-seconds taken by all reduce tasks=3882

Total megabyte-seconds taken by all map tasks=7640064

Total megabyte-seconds taken by all reduce tasks=3975168

Map-Reduce Framework

Map input records=2

Map output records=4

Map output bytes=41

Map output materialized bytes=61

Input split bytes=220

Combine input records=4

Combine output records=4

Reduce input groups=3

Reduce shuffle bytes=61

Reduce input records=4

Reduce output records=3

Spilled Records=8

Shuffled Maps =2

Failed Shuffles=0

Merged Map outputs=2

GC time elapsed (ms)=94

CPU time spent (ms)=3510

Physical memory (bytes) snapshot=698580992

Virtual memory (bytes) snapshot=2897805312

Total committed heap usage (bytes)=603979776

Shuffle Errors

BAD_ID=0

CONNECTION=0

IO_ERROR=0

WRONG_LENGTH=0

WRONG_MAP=0

WRONG_REDUCE=0

File Input Format Counters

Bytes Read=25

File Output Format Counters

Bytes Written=25

5、查看结果

[wangqi@node001 input]$ hdfs dfs -ls -R /

drwxr-xr-x - wangqi supergroup 0 2015-12-28 16:14 /user

drwxr-xr-x - wangqi supergroup 0 2015-12-28 16:18 /user/wangqi

drwxr-xr-x - wangqi supergroup 0 2015-12-28 16:17 /user/wangqi/in

-rw-r--r-- 2 wangqi supergroup 12 2015-12-28 16:17 /user/wangqi/in/test1.txt

-rw-r--r-- 2 wangqi supergroup 13 2015-12-28 16:17 /user/wangqi/in/test2.txt

drwxr-xr-x - wangqi supergroup 0 2015-12-28 16:18 /user/wangqi/out

-rw-r--r-- 2 wangqi supergroup 0 2015-12-28 16:18

/user/wangqi/out/_SUCCESS

-rw-r--r-- 2 wangqi supergroup 25 2015-12-28 16:18

/user/wangqi/out/part-r-00000

[wangqi@node001 input]$ hdfs dfs -cat /user/wangqi/out/part-r-00000

hadoop 1

hello 2

world 1

异常处理

Got exception: org.apache.hadoop.yarn.exceptions.YarnException: Unauthorized request to start container.

This token is expired. current time is 1451316339594 found 1451288164469

Note: System times on machines may be out of sync. Check system time and time zones.

这是因为datanode与namenode之间未设置时间同步,所以引起该异常。解决方案是将多个datanode与namenode进行时间同步,即在每个服务器上执行ntpdate time.nist.gov命令,如下:

[wangqi@node002 ~]$ sudo ntpdate time.nist.gov

附:SSH原理

为了更好的理解SSH免密码登录原理,我们先来说说SSH的安全验证,SSH采用的是”非对称密钥系统”,即耳熟能详的公钥私钥加密系统,其安全验证又分为两种级别。

1. 基于口令的安全验证

这种方式使用用户名密码进行联机登录,一般情况下我们使用的都是这种方式。整个过程大致如下:

(1)客户端发起连接请求。

(2)远程主机收到用户的登录请求,把自己的公钥发给客户端。

(3)客户端接收远程主机的公钥,然后使用远程主机的公钥加密登录密码,发送给远程主机。

(4)远程主机用自己的私钥,解密登录密码,如果密码正确,就同意用户登录。

在linux上,如果你是第一次登录对方主机,系统会出现下面的提示:

The authenticity of host '10.254.201.202 (10.254.201.202)' can't be established.

RSA key fingerprint is a6:fb:54:f6:ae:54:dd:c3:23:12:c8:2d:ca:d6:3f:12.

这段话的意思是,无法确认host主机的真实性,只知道它的公钥指纹,问你还想继续连接吗?

所谓"公钥指纹",是指公钥长度较长(这里采用RSA算法,长达1024位),很难比对,所以对其进行MD5计算,将它变成一个128位的指纹再进行比较,就容易多了,上例中的是a6:fb:54:f6:ae:54:dd:c3:23:12:c8:2d:ca:d6:3f:12。

很自然的一个问题就是,用户怎么知道远程主机的公钥指纹应该是多少?回答是没有好办法,远程主机必须在自己的网站上贴出公钥指纹,以便用户自行核对。

假定经过风险衡量以后,用户决定接受这个远程主机的公钥。

Are you sure you want to continue connecting (yes/no)? yes

系统会出现一句提示,表示10.254.201.202主机已经得到认可。

Warning: Permanently added '10.254.201.202' (RSA) to the list of known hosts.

然后,会要求输入密码。

wangqi@10.254.201.202's password:

如果密码正确,就可以登录了。

当远程主机的公钥被接受以后,它就会被保存在文件$HOME/.ssh/known_hosts之中。下次再连接这台主机,系统就会认出它的公钥已经保存在本地了,从而跳过警告部分,直接提示输入密码。

每个SSH用户都有自己的known_hosts文件,分别在自己的$HOME目录下,此外操作系统也有一个这样的文件,通常是/etc/ssh/ssh_known_hosts,保存一些对所有用户都可信赖的远程主机的公钥。

注:当网络中有另一台冒牌服务器冒充远程主机时,客户端的连接请求被服务器B拦截,服务器B将自己的公钥发送给客户端,客户端就会将密码加密后发送给冒牌服务器,冒牌服务器就可以拿自己的私钥获取到密码,然后为所欲为。因此当第一次链接远程主机时,在上述步骤的第(3)步中,会提示您当前远程主机的”公钥指纹”,以确认远程主机是否是正版的远程主机,如果选择继续后就可以输入密码进行登录了,当远程的主机接受以后,该台服务器的公钥就会保存到 ~/.ssh/known_hosts文件中。

2. 基于公钥的安全验证

使用密码登录,每次都必须输入密码,非常麻烦。好在SSH还提供了公钥登录,可以省去输入密码的步骤。

所谓"公钥登录",原理很简单,就是用户将自己的公钥储存在远程主机上。登录的时候,远程主机会向用户发送一段随机字符串,用户用自己的私钥加密后,再发回来。远程主机用事先储存的公钥进行解密,如果成功,就证明用户是可信的,直接允许登录shell,不再要求输入密码,这和之前的ssh账号密码也没有直接关系。

这种方法要求用户必须提供自己的公钥。如果没有现成的,可以直接用ssh-keygen生成一个:

$ ssh-keygen

运行上面的命令以后,系统会出现一系列提示,可以一路回车。其中有一个问题是,要不要对私钥设置口令(passphrase),如果担心私钥的安全,这里可以设置一个。

运行结束以后,在$HOME/.ssh/目录下,会新生成两个文件:id_rsa.pub和id_rsa。前者是你的公钥,后者是你的私钥。

这时再输入下面的命令,将公钥传送到远程主机host上面:

scp id_rsa.pub wangqi@10.254.201.202:~/

好了,从此你再登录远程主机,就不需要输入密码了。

如果还是不行,就打开远程主机的/etc/ssh/sshd_config这个文件,检查下面几行前面"#"注释是否取掉。

RSAAuthentication yes

PubkeyAuthentication yes #是否允许使用公钥验证方式登录

AuthorizedKeysFile .ssh/authorized_keys #允许登录的主机的公钥存放文件,默认为用#户家目录下的.ssh/authorized_keys

然后,重启远程主机的ssh服务。

3.关于authorized_keys文件

远程主机将用户的公钥,保存在登录后的用户主目录的$HOME/.ssh/authorized_keys文件中。公钥就是一段字符串,只要把它追加在authorized_keys文件的末尾就行了。

如果不使用上面的ssh-copy-id命令,改用下面的命令也可以:

# scp -P 22 id_rsa.pub root@192.168.1.77:/root/.ssh/authorized_keys

root@192.168.1.77's password: <-- 输入机器Server的root用户密码

id_rsa.pub 100% 218 0.2KB/s 00:00

如果远程主机的authorized_keys文件已经存在,也可以往里添加公钥:

先将公钥文件上传到远程主机中,

#scp -P 22 ~/.ssh/id_rsa.pub root@192.168.1.91:/root/

SSH到登陆到远程主机,将公钥追加到 authorized_keys 文件中

cat /root/id_rsa.pub >> /root/.ssh/authorized_keys

或直接运行命令:

cat ~/.ssh/id_dsa.pub|ssh -p 22 root@192.168.1.91 `cat - >> ~/.ssh/authorized_keys`

写入authorized_keys文件后,公钥登录的设置就完成了。

 

Hadoop需要使用SSH协议,namenode将使用SSH协议启动namenode和datanode进程。以namenode到datanode为例子:Namenode作为客户端,要实现无密码公钥认证,连接到服务端datanode上时,需要在namenode上生成一个密钥对,包括一个公钥和一个私钥,而后将公钥复制到datanode上。当namenode通过ssh连接datanode时,datanode就会生成一个随机数并发送给namenode。namenode收到随机数之后再用私钥进行加密,并将加密数回传给datanode,datanode用公钥解密成功后就允许namenode进行连接了。这就是一个公钥认证过程,其间不需要用户手工输入密码。重要过程是将客户端namenode公钥复制到datanode上。

posted @ 2016-01-05 11:11  codeplayplus  阅读(980)  评论(0编辑  收藏  举报